【问题标题】:Blazor Complex Validation between two nested Objects两个嵌套对象之间的 Blazor 复杂验证
【发布时间】:2022-08-15 20:31:21
【问题描述】:

假设我们有一个简单的对象,其中包含两个另一种类型

public class Parent
{
     [ValidateComplexType]
     public Child Child1 { get; set; }

     [ValidateComplexType]
     public Child Child2 { get; set; }
}
 
public class Child : IValidatableObject
{
     public String Name { get; set; } = String.Empty
     
     public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
     {
         return new ValidationResult(\"Error\", new[] { nameof(Name) })
     }
}

我设法按照建议使用ObjectGraphDataAnnotationsValidator 进行嵌套验证 https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#nested-models-collection-types-and-complex-types

现在假设我不希望 Child2 与 Child 1 具有相同的 Name,因此我需要比较它们的 Name 属性并在 Child2 输入字段上显示错误。 如果我通过将IValidatableObject 添加到Parent 并在验证方法中返回new ValidationResult(\"Error\", new[] { nameof(Child2.Name) }) 来执行此操作,这实际上不会将该字段设置为无效。

我考虑为每个孩子添加一个Func&lt;Child, Boolean&gt;,然后在我实例化父对象时设置它,看起来像child =&gt; child == Child2 &amp;&amp; Child2.Name == Child1.Name,它可以工作,但在我看来它非常令人困惑。 如何正确执行此操作?

  • 大佬有进展吗?

标签: c# asp.net-core blazor


【解决方案1】:

以我的拙见,您需要在此处使用custom validation 来检查 Child2 是否与 Child1 具有相同的名称。我在 blazor 服务器应用程序中进行了测试。我的模型有 2 个属性,即 Name1 和 Name2。

public class ExampleModel
{
    [Required]
    public UserTest userName1 { get; set; }
    [Required]
    public UserTest userName2 { get; set; }
}

public class UserTest {
    [StringLength(10, ErrorMessage = "Name is too long.")]
    public string userName { get; set; }
}


@page "/form-example-1"
@using BlazorAppServer.Model
<h3>FormExample1</h3>

<EditForm Model="@exampleModel" OnValidSubmit="@HandleValidSubmit">
    <CustomValidation @ref="customValidation" />
    <DataAnnotationsValidator />
    <ValidationSummary />

    <InputText id="name" @bind-Value="exampleModel.userName1.userName" />
    <InputText id="name" @bind-Value="exampleModel.userName2.userName" />

    <button type="submit">Submit</button>
</EditForm>

@code {
    private ExampleModel exampleModel = new() { userName1 = new UserTest { userName="asdfgh"}, userName2 = new UserTest { userName="hgfdsa"} };
    private CustomValidation customValidation;

    private void HandleValidSubmit()
    {
        customValidation.ClearErrors();
        var a = exampleModel.userName1.userName;
        var b = exampleModel.userName2.userName;
        var errors = new Dictionary<string, List<string>>();
        if (a == b)
        {
            errors.Add(nameof(exampleModel.userName2.userName), new() { "name2 can't be the same as name1" });
        }
        if (errors.Any())
        {
            customValidation.DisplayErrors(errors);
        }
    }
}
    
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System;
using System.Collections.Generic;

namespace BlazorAppServer
{
    public class CustomValidation : ComponentBase
    {
        private ValidationMessageStore messageStore;

        [CascadingParameter]
        private EditContext CurrentEditContext { get; set; }
        protected override void OnInitialized()
        {
            if (CurrentEditContext == null)
            {
                throw new InvalidOperationException(
                    $"{nameof(CustomValidation)} requires a cascading " +
                    $"parameter of type {nameof(EditContext)}. " +
                    $"For example, you can use {nameof(CustomValidation)} " +
                    $"inside an {nameof(EditForm)}.");
            }

            messageStore = new(CurrentEditContext);

            CurrentEditContext.OnValidationRequested += (s, e) =>
                messageStore.Clear();
            CurrentEditContext.OnFieldChanged += (s, e) =>
                messageStore.Clear(e.FieldIdentifier);
        }

        public void DisplayErrors(Dictionary<string, List<string>> errors)
        {
            foreach (var err in errors)
            {
                messageStore.Add(CurrentEditContext.Field(err.Key), err.Value);
            }

            CurrentEditContext.NotifyValidationStateChanged();
        }

        public void ClearErrors()
        {
            messageStore.Clear();
            CurrentEditContext.NotifyValidationStateChanged();
        }
    }
}

【讨论】:

  • 很抱歉,但在尝试之后,如果您有嵌套模型,这不会将正确的字段设置为无效。在您的情况下,您将 exampleModel 作为 EditForm 的模型,但在我的情况下,我将拥有 exampleModel.NestedModel.Name1
  • 我已经用嵌套模型更新了我的代码,它也运行良好,请检查它。我没有更改CustomValidation 中的代码
  • 您可以在 Microsoft.AspNetCore.Components.Forms 中使用 <ObjectGraphDataAnnotationsValidator ></ObjectGraphDataAnnotationsValidator>。您也不需要额外的更改,它可以与editform一起正常工作
  • (代表@Nikolas 发表评论):不幸的是,@TinyWang 的代码似乎不起作用。我已经创建了一个位于 [source][1] 的项目,其中包含我自己的示例,其中包含嵌套对象和 Tiny Wang 的代码在 url (/form-example-1) [1]:github.com/nifragos/blazor-nested-validation-problem
【解决方案2】:

你可以用这个

https://code-maze.com/complex-model-validation-in-blazor/

Microsoft.AspNetCore.Components.DataAnnotations.Validation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-22
    • 2021-01-22
    • 2022-01-07
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    相关资源
    最近更新 更多