我有一个扩展方法来检查特定字段是否有效。
public static bool IsValid(this EditContext editContext, string fieldName)
{
var fieldIdentifier = editContext.Field(fieldName);
editContext.NotifyFieldChanged(fieldIdentifier);
var result = !editContext.GetValidationMessages(fieldIdentifier).Any();
Console.WriteLine($"{fieldName} : {result}");
return result;
}
它对非复杂领域很好,但对复杂领域却不起作用。e.g
我的模型是
public class RegisterCompanyRequest
{
[Required(ErrorMessage = "Company Name is required")]
[MaxLength(200, ErrorMessage = "Maximum allowed length for company name is 200 characters")]
public string NameEn { get; set; }
[ValidateComplexType]
public List<CompanyLocation> CompanyLocations { get; set; }
[ValidateComplexType]
public CompanyAdminInfo CompanyAdminInfo { get; set; } = new CompanyAdminInfo();
}
public class CompanyAdminInfo
{
[Required(ErrorMessage = "Full name is required")]
[MaxLength(200, ErrorMessage = "Maximum allowed length for full name is 200 characters")]
public string FullName { get; set; }
}
public class CompanyLocation
{
public int Id { get; set; }
[Required]
[MaxLength(200, ErrorMessage = "Maximum allowed length for location name is 200 characters")]
public string Name { get; set; }
}
如果我通过那个方法NameEn
,如果验证失败,它返回false,否则返回true,但是如果我传递它CompanyLocations[0].Name
或CompanyAdminInfo.FullName
,它总是返回true。
如何对模型中的嵌套对象实现相同的功能?
复制:将下面的代码复制到新的blazor项目中。还安装以下包以验证复杂类型( install Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4)
@page "/"
@using System.ComponentModel.DataAnnotations
<p>"Name" : @company.Name <span>@nameValid</span> </p>
<p>"Admin Name" : @company.Admin.Name <span>@adminNameValid</span> </p>
<EditForm EditContext="editContext">
<ObjectGraphDataAnnotationsValidator />
<input type="text" @bind-value="@company.Name"/>
<input type="text" @bind-value="@company.Admin.Name"/>
<button @onclick="Validate" type="submit">Validate</button>
</EditForm>
@code
{
private bool nameValid, adminNameValid;
private Company company = new Company();
EditContext editContext { get; set; }
protected override async Task OnInitializedAsync()
{
editContext = new(company);
}
private async Task Validate()
{
var isValid = IsValid(editContext, "Name");
nameValid = isValid;
isValid = IsValid(editContext, "Admin.Name");
adminNameValid = isValid;
}
public bool IsValid(EditContext editContext, string fieldName)
{
var fieldIdentifier = editContext.Field(fieldName);
editContext.NotifyFieldChanged(fieldIdentifier);
return !editContext.GetValidationMessages(fieldIdentifier).Any();
}
public class Company
{
[Required]
public string Name { get; set; }
[ValidateComplexType] /*(Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4)*/
public Admin Admin { get; set; } = new Admin();
}
public class Admin
{
[Required]
public string Name { get; set; }
}
}
发布于 2022-05-30 20:59:26
我猜你的代码中有两个反模式。
第一个是用手打电话给editContext.NotifyFieldChanged(fieldIdentifier);
。让Blazor处理通知。
第二个是提交,在我看来,您应该避免调用submit
按钮上的函数。相反,可以在OnValidSubmit
或OnInvalidSubmit
组件级别使用EditForm
,或者将函数绑定到editContext.OnValidationStateChanged
,如我正在运行的示例中所示。
@page "/"
@using System.ComponentModel.DataAnnotations
@implements IDisposable
<EditForm EditContext="editContext" OnValidSubmit="ValidSubmit">
<ObjectGraphDataAnnotationsValidator />
<InputText type="text" @bind-Value="@company.Name" />
<ValidationMessage For="@(() => company.Name)" />
<InputText type="text" @bind-Value="@company.Admin.Name" />
<ValidationMessage For="@(() => company.Admin.Name)" />
<button type="submit">Validate</button>
</EditForm>
<p>"Name" : @company.Name <span>@nameValid</span> </p>
<p>"Admin Name" : @company.Admin.Name <span>@adminNameValid</span> </p>
@code
{
private bool? nameValid, adminNameValid;
private Company company = new Company();
EditContext editContext { get; set; } = default!;
protected override void OnInitialized()
{
editContext = new(company);
editContext.OnValidationStateChanged += HandleValidationStateChanged;
}
private void HandleValidationStateChanged(object? o, ValidationStateChangedEventArgs args)
{
var name_field = FieldIdentifier.Create( () => company.Name );
nameValid = IsValid(editContext, name_field);
var admin_name_field = FieldIdentifier.Create( () => company.Admin.Name );
adminNameValid = IsValid(editContext, admin_name_field);
}
private void ValidSubmit()
{
nameValid = true;
adminNameValid = true;
}
public bool IsValid(EditContext editContext, FieldIdentifier fieldIdentifier)
=>
!editContext.GetValidationMessages(fieldIdentifier).Any();
public class Company
{
[Required]
[StringLength(3, ErrorMessage = "Identifier too long (3 character limit).")]
public string Name { get; set; } = default!;
[ValidateComplexType] /*(Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4)*/
public Admin Admin { get; set; } = new Admin();
}
public class Admin
{
[Required]
[StringLength(3, ErrorMessage = "Identifier too long (3 character limit).")]
public string Name { get; set; } = default!;
}
public void Dispose()
{
if (editContext is not null)
{
editContext.OnValidationStateChanged -= HandleValidationStateChanged;
}
}
}
发布于 2022-05-31 05:56:39
创建了一个扩展方法。
public static class EditContextHelper
{
public static bool IsValid(this EditContext editContext, Expression<Func<Object>> field)
{
var fieldIdentifier = FieldIdentifier.Create(field);
editContext.NotifyFieldChanged(fieldIdentifier);
return !editContext.GetValidationMessages(fieldIdentifier).Any();
}
}
用它就像,
var field = model.CompanyLocations[0].Name
var result = EditContext.IsValid(field);
在我的例子中,我使用数组遍历像这样的指定字段。
var isValid = false;
var fieldsToValidate = new Expression<Func<Object>>[]
{
() => model.NameEn, () => (model.Address), () => model.Lattitude,
() => model.Longitude , () => (model.Tel1), () => (model.Tel2), () => (model.Mobile), () => (model.Whatsapp),
() => (model.Email), () => (model.Url), () => (model.TaxNumber)
};
foreach (var field in fieldsToValidate)
{
var result = EditContext.IsValid(field);
if (!result)
{
isValid = false;
}
//doing something if any of the fields is wrong.
}
https://stackoverflow.com/questions/72430616
复制相似问题