流畅验证 - 检查重复值



我在 Blazor Server 应用程序中有一个 EditForm,我想检查 InputText 值是否在列表中。 如何将要比较的列表从我的 UI 传递到验证器类进行比较?

我尝试比较行中的 @bind 值并封装验证消息,但是当封装函数测试 true 时,它会跳过验证消息。

<EditForm Model="@resourceToBeCreated">
<FluentValidationValidator ValidatorType=typeof(ResourceValidator)/>
@if (resourcesSortedCollection.FirstOrDefault(x => x.Name == resourceToBeCreated.Name) != null)
{
<CustomValidationMessage For="() => resourceToBeCreated.Name" /> 
}

<InputTextOnInput @bind-Value="@resourceToBeCreated.Name" class="form-control"  placeholder="Name..." />
</EditForm>

我显然可以在@code部分中执行此操作或类似操作,但是在inupt上没有收到验证弹出窗口。

所以问题是,我如何将此列表传递给验证器类进行比较?

编辑 1: InputTextOnInput 组件:

@inherits InputText
<input @attributes="AdditionalAttributes"
class="@CssClass"
value="@CurrentValue"
@oninput="EventCallback.Factory.CreateBinder<string>(this, __value => CurrentValueAsString = __value, CurrentValueAsString)" />

编辑2: 一种潜在的解决方法,同时仍使用流畅的验证。

1、为模型添加新属性:

public List<string> ResourceNames { get; set; }

2,在浏览器中创建新资源时,更新模型中的该属性

resourceToBeCreated.ResourceNames = resourcesSortedCollection.Select(x => x.Name).ToList();

3、在流畅验证中编写规则

RuleFor(x => x.Name).Null().When(x => x.ResourceNames.Contains(x.Name)).WithMessage("Duplicate resource name");

不确定这是否是最好的方法(代码气味?),但它现在有效。 无论哪种方式,我都必须创建一个包含所有资源名称的字符串列表。 如果有更直接的方法将 resourcesSortedCollection 对象传递给验证人 id 喜欢理解。

首先是继承的InputText控件。 这将覆盖TryParseValueFromString并在那里进行验证。

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System.Diagnostics.CodeAnalysis;
namespace BlazorApp1.Pages;
public class InputTextValidated : InputText
{
[Parameter, EditorRequired] public IEnumerable<string>? CheckList { get; set; }
{ get; set; }
protected override bool TryParseValueFromString(string? value, out string? result, [NotNullWhen(false)] out string? validationErrorMessage)
{
result = null;
validationErrorMessage = null;
var isValid = this.CheckList is not null
&& this.CheckList.Any(item => item.Equals(value, StringComparison.InvariantCultureIgnoreCase));
if (isValid)
result = value;
else
validationErrorMessage = "You must enter a value in the validation list";
return isValid;
}
}

还有一个测试页面:

@page "/"
<PageTitle>Index</PageTitle>
<EditForm Model=this.model>
<DataAnnotationsValidator />
<InputTextValidated class="form-control" CheckList=Countries @bind-Value="@this.model.Country" />
<ValidationSummary />
</EditForm>
<div>
Country : @model.Country
</div>
@code {
private DataModel model = new DataModel();
private List<string> Countries = new List<string> { "UK", "Spain" };
public class DataModel
{
public string? Country;
}
}

作为替代方法,您可以使用/生成输入列表控件。

验证的工作原理

验证数据保存在与EditContext相关联的ValidationMessageStore中。ValidationMessageStore是键/值对的组合集合:

  • 定义为FieldIdentifier的字段 [模型作为object,字段名称定义为string]
  • 验证消息为string

每个验证提供程序都有自己的消息存储库,可以清除消息并向其中添加消息。 它只能对其自己的邮件存储具有写入/删除访问权限。 提供程序获取EditForm级联的EditContext,创建与EditContext关联的消息存储,并将消息记录到该存储区并从该存储区清除消息。FluentValidationValidatorDataAnnotationsValidator、您编写的任何与EditContext交互的InputBase控件或类都是具有与EditContext关联的消息存储的提供程序。

ValidationSummaryValidationMessage都是消费者。 它们通过级联EditContext与与 EditContext 关联的消息存储库进行交互。 所有消息都以只读形式提供。ValidationMessageFor表达式构造一个FieldIdentifier来筛选消息。

我认为 id 会抛出一个答案,因为我在做其他事情时偶然发现了一个答案,它可能会帮助另一个答案。

您可以在实例化验证程序时将要验证的值传递到验证程序中。在这种情况下,通过构造函数将 BaseResourceMoldes 列表传递到 ResouceValidator 中。 由于列表不会在实例化和验证之间更改,因此这是合适的。

然后使用 Must 扩展,该扩展会将您正在验证的参数传递到调用的函数中以测试布尔值。 在这种情况下.Must(IsUnique) 将 x.Name 传递到 IsUnique(string arg1) 中并返回一个布尔值。

语法可能与上面的示例略有不同,因为代码库在那时和现在之间会发生变化,但概念是相同的。

具有要验证的表单的类:

[Parameter] public List<BaseResourceModel> Resources { get; set; }
ResourceValidator resourceValidator;
protected override void OnInitialized()
{
resourceValidator = new ResourceValidator(Resources);
}

然后是 ResourceValidator 类:

private List<BaseResourceModel> _resources;
private void ResourceValidator(List<BaseResourceModel> resources)
{
_resources = resources;
RuleFor(x => x.Name).NotEmpty().Must(IsUnique).WithMessage("Resource name must be unique");
}
private bool IsUnique(string arg1)
{
bool isUnique = true;
foreach (var resource in _resources)
{
if (resource.Name == arg1)
{
isUnique = false;
}
}
return isUnique;
}

我假设如果列表有可能更改,您也可以异步执行此操作。 流畅验证具有异步方法。

相关内容

  • 没有找到相关文章

最新更新