【问题标题】:How to validate a model in Blazor server app without triggering validation messages?如何在 Blazor 服务器应用程序中验证模型而不触发验证消息?
【发布时间】:2021-06-29 22:09:24
【问题描述】:

我正在开发一个 Blazor 服务器应用程序,该应用程序通过几个步骤收集用户信息。父页面创建一个模型(我们称之为 MainModel),它是子组件中使用的模型的数据集合,父将此模型作为级联参数传递给子,子收集更多信息并填写该模型中的匹配参数。

当组件被加载时,它会加载自己的模型。修改输入时,如果通过验证,我需要检查 ChildModel 并将其添加到 MainModel。根据 Blazor 文档,我将 FieldChanged 事件用于 EditContext。


    <EditForm EditContext="editContext">
    <DataAnnotationsValidator/>
    <div class="col-md-6">
        <label for="FirstName" class="form-label">First Name</label>
        <InputText type="text" @bind-Value="Model.FirstName" class="form-control" 
     name="FirstName"/>
        <ValidationMessage For="@(() => Model.FirstName)" />
    </div>
    <div class="col-md-3">
        <label for="LastName" class="form-label">Last Name</label>
        <InputText type="text" @bind-Value="Model.LastName" class="form-control" 
        name="LastName"/>
        <ValidationMessage For="@(() => Model.LastName)" />
    </div>

    <div class="col-md-3">
        <label for="Age" class="form-label">Age</label>
        <InputText type="text" @bind-Value="Model.Age" class="form-control" name="Age"/>
        <ValidationMessage For="@(() => Model.Age)" />
    </div>
    </EditForm>


    @code{
    [CascadingParameter]
    public MainModel MainModel { get; set; }

    private ChildModel Model {get; set; }


    private EditContext editContext;

    protected override async Task OnInitializedAsync()
    {
        editContext = new EditContext(Model);
        editContext.OnFieldChanged += EditContext_OnFieldChanged;
        base.OnInitialized();
    }

    private async void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
    {
        if(editContext.Validate()) //<-- this shows validation messages
        {
            //copy child model to main model here
        }
    }
}

问题是,一旦修改了字段,就会按预期触发此事件,并且验证模型会触发所有输入的验证消息,因为此时没有填写其他必填字段.

有没有办法在不触发验证消息的情况下验证模型?

也许我需要对 ValidationMessageStore 做一些事情,但我还没有弄清楚。我可以通过查看输入同级的已修改和无效类来切换单个验证消息,但我确信 Blazor 对此有解决方案。

到目前为止我还没有答案,所以我目前的实现是这样的:

当调用 EditContext.Validate() 时,我最初使用 css 隐藏消息,并且仅在输入被修改且无效时才显示它们:

.validation-message {
  display: none; 
}

input.modified.invalid {
  border: 1px solid red;
  position: relative; 
}

input.modified.invalid + .validation-message {
    position: absolute;
    margin-top: -10px;
    color: red;
    background: #fdf2f2;
    border: 1px solid #ffdede;
    padding: 5px;
    display: block;
    z-index: 1; 
}

【问题讨论】:

  • 看看 Fluentvalidator for .net blazor 我相信有一个可行的。
  • @EricKing 很有帮助,但不是我想要的。我不想验证单个字段,我想知道当任何输入发生更改而不显示所有输入的验证消息时整个模型是否有效。这背后的原因是因为我有一个下一步按钮,一旦模型有效就会显示。
  • 酷。想我会分享,以防它激发一些见解。
  • @EricKing 我很感激。

标签: c# validation blazor blazor-server-side


【解决方案1】:

不是直接的答案,但 Chris Sainty 为 @AliK 提到的 FluentValidator 创建了一个 blazor 包装器。他在他的书中和blog 中描述了非常优雅的解决方案。比自己滚动要简单得多。

  1. 添加他的Blazored Nuget package

dotnet add package FluentValidation

  1. 在 EditForm 中插入他的组件,替换较弱的 DataAnnotationsValidator:

&lt;FluentValidationValidator @ref="fluentValidationValidator" /&gt;

  1. 创建一个变量来保存验证器引用:

private FluentValidationValidator fluentValidationValidator;

  1. 为您的子模型设置fluent validations。真正强大的工具,已经存在了一段时间。我已经能够设置复杂的记录级别验证、重复检查等。

  2. 现在您可以很容易地在代码中进行验证:

    var isValid = fluentValidationValidator.Validate(opts => opts.IncludeAllRuleSets());
    if (!isValid) return;  // show errors
    // else, proceed
    

【讨论】:

  • 我知道这个库,但我不确定我是否应该安装和实现第三方库只是为了知道模型是否有效。如果示例中的 Validate 方法是 void 方法,它会触发消息吗?
  • @PersyJack 取决于您的用例。知道模型是否有效是非常关键的,对我们来说,这个工具对于除了最简单的应用程序(即那些愚蠢的天气服务示例)之外的所有应用程序都是必不可少的。 validate 方法贯穿您的验证——正如我所说,这可能相当复杂。不确定您所说的“无效方法”是什么意思,但是可以将流畅的规则配置为仅在满足某些条件时运行。消息显示通过类似 DataAnnotationsValidator 的 .Net Core 机制自动发生。
  • 关于第 3 方方面,为了节省时间,我将其归为 Automapper 或 Bootstrap 类别。
【解决方案2】:

我通常做的是有一个 bool 变量来捕获 editContext 是否有效。类似prive bool _modelHasBeenModified {get; set;} = false;

然后我会运行验证_modelHasBeenModified = editContext.Validate();

然后我将重置验证,因此不会显示任何验证消息:editContext.MarkAsUnmodified(); - 这样,我仍然可以在 _modelHasBeenModified 中保留模型有效性。

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 2020-09-05
    • 2021-01-04
    • 1970-01-01
    • 2021-04-30
    相关资源
    最近更新 更多