Razor 页面流畅的验证服务器端不起作用

Posted

技术标签:

【中文标题】Razor 页面流畅的验证服务器端不起作用【英文标题】:Razor pages fluent validation server side not working 【发布时间】:2021-10-07 18:57:48 【问题描述】:

我使用流利的验证来验证我的表单。 我使用 asp.net 核心(剃须刀页面)。 它在客户端正常工作,但是当我删除 jquery 验证脚本来测试服务器端验证时,我发现它不起作用并且 ModelState 为真。 我该如何解决这个问题。有什么解决办法吗?

这是页面模型属性

/// <summary>
    /// Gets or sets the user role name
    /// </summary>
    [HamiResourceDisplayName("Security.Role.Fields.Name")]
    [BindProperty]
    public string Name  get; set; 

    /// <summary>
    /// Gets or sets the user role system name
    /// </summary>
    [HamiResourceDisplayName("Security.Role.Fields.SystemName")]
    [BindProperty]
    [PageRemote(
        //ErrorMessage = "Already exists",
        AdditionalFields = "__RequestVerificationToken",
        HttpMethod = "Post",
        PageHandler = "CheckSystemName"
    )]
    public string SystemName  get; set; 

    /// <summary>
    /// Gets or sets a value indicate whether the user role is for managers
    /// </summary>
    [HamiResourceDisplayName("Security.Role.Fields.ManagerRole")]
    [BindProperty]
    public bool IsManagerRole  get; set; 

    /// <summary>
    /// Gets or sets a value indicating whether the level of manager if it's a manager role
    /// </summary>
    [HamiResourceDisplayName("Security.Role.Fields.ManagerLevel")]
    [BindProperty]
    public int? ManagerLevel  get; set; 

这是 OnPost

    public async Task<IActionResult> OnPostAsync()
    
        if (!ModelState.IsValid) return Page();
        var role = new Role()
        
            Name = Name,
            Inactive = false,
            IsSystemRole = false,
            SystemName = SystemName,
            IsManagerRole = IsManagerRole,
            ManagerLevel = IsManagerRole ? ManagerLevel : null
        ;
        await _userService.InsertRoleAsync(role);
        return RedirectToPage("/Security/Roles/Index");
    

最后这是我的验证

public class CreateRolesValidator : AbstractValidator<CreateModel>

    public CreateRolesValidator(ILocalizationService localizationService)
    
        RuleFor(x => x.Name).NotNull().WithMessageAwait(localizationService.GetResourceAsync("Security.Role.Fields.Name.Required"));
        RuleFor(x => x.SystemName).NotNull().WithMessageAwait(localizationService.GetResourceAsync("Security.Role.Fields.SystemName.Required"));
        //RuleFor(x => x.SystemName).IsUniqueRoleSystemName().WithMessageAwait(localizationService.GetResourceAsync("Security.Role.SystemName.SystemNameAlreadyExists"));
        RuleFor(x => x.ManagerLevel).NotNull().DependentRules(() =>
        
            RuleFor(x => x.IsManagerRole).Must(x => x.Equals(true));
        ).WithMessageAwait(localizationService.GetResourceAsync("Security.Role.Fields.ManagerLevel.Required"));
    

例如,“Name”的 NotEmpty() 可以在客户端正常工作,但不能在服务器端正常工作,并且不会被视为无效模型状态。

【问题讨论】:

我应该提到我使用 .NotEmpty 和 .NotNull 形成了一些角色,结果是一样的。 【参考方案1】:

尝试创建一个单独的类来存储模型属性,然后为其添加验证并在剃须刀页面中使用。

例如:创建 RoleViewModel:

public class RoleViewModel

    /// <summary>
    /// Gets or sets the user role name
    /// </summary> 
    [BindProperty]
    public string Name  get; set; 

    /// <summary>
    /// Gets or sets the user role system name
    /// </summary> 
    [BindProperty]
    [PageRemote(
        //ErrorMessage = "Already exists",
        AdditionalFields = "__RequestVerificationToken",
        HttpMethod = "Post",
        PageHandler = "CheckSystemName"
    )]
    public string SystemName  get; set; 

    /// <summary>
    /// Gets or sets a value indicate whether the user role is for managers
    /// </summary> 
    [BindProperty]
    public bool IsManagerRole  get; set; 

    /// <summary>
    /// Gets or sets a value indicating whether the level of manager if it's a manager role
    /// </summary> 
    [BindProperty]
    public int? ManagerLevel  get; set; 

public class CreateRolesValidator : AbstractValidator<RoleViewModel>

    public CreateRolesValidator()
    
        RuleFor(x => x.Name).NotNull();
        RuleFor(x => x.SystemName).NotNull();
        //RuleFor(x => x.SystemName).IsUniqueRoleSystemName().WithMessageAwait(localizationService.GetResourceAsync("Security.Role.SystemName.SystemNameAlreadyExists"));
        RuleFor(x => x.ManagerLevel).NotNull().DependentRules(() =>
        
            RuleFor(x => x.IsManagerRole).Must(x => x.Equals(true));
        );
    

然后,在 ConfigureServices 方法中注册验证服务:

    public void ConfigureServices(IServiceCollection services)
    
        services.AddRazorPages().AddFluentValidation();

        services.AddTransient<IValidator<RoleViewModel>, CreateRolesValidator>();
    

然后在Create.cshtml.cs文件中:

public class CreateModel : PageModel

    [BindProperty]
    public RoleViewModel Role  get; set; 
    public void OnGet()
    
    
    public async Task<IActionResult> OnPostAsync()
    
        if (!ModelState.IsValid) return Page();
       
        return RedirectToPage("/Index");
    

和 Create.cshtml:已经禁用了客户端验证

@page
@model RazorWebApplication.Pages.CreateModel

<form method="post">

    Name: <input asp-for="Role.Name" class="form-control" /> <span asp-validation-for="Role.Name" class="text-danger"></span>
    <br />
    SystemName: <input asp-for="Role.SystemName" class="form-control" /> <span asp-validation-for="Role.SystemName" class="text-danger"></span>
    <br />
    IsManagerRole: <input asp-for="Role.IsManagerRole" class="form-control" /> <span asp-validation-for="Role.IsManagerRole" class="text-danger"></span>
    <br />
    ManagerLevel: <input asp-for="Role.ManagerLevel" class="form-control" /> <span asp-validation-for="Role.ManagerLevel" class="text-danger"></span>

    <br /><br />
    <input type="submit" value="submtit" />
</form>

@*@section Scripts 
    @await Html.RenderPartialAsync("_ValidationScriptsPartial");
*@

结果如下:

【讨论】:

真的很坦克。它解决了我的问题。您知道在使用单独的类时如何使用远程验证吗?这个问题有解决办法吗? @HamedNaghdi,很高兴听到回复可以帮助您解决问题。对于远程验证,我在Fluent验证文档中没有找到相关描述,只找到this thread。如果不使用 Fluent Validation,可以在页面模型中添加属性(远程验证),而不是添加到上面的类中(使用 fluent 验证),然后参考this article 实现远程验证。 @HamedNaghdi,既然这个问题已经解决了,而且远程验证是另一个问题,如果您还有任何问题,我建议您可以[关闭此线程]((***.com/help/someone-answers)) 并打开一个关于新问题的新帖子,然后社区成员会看到它并帮助您解决问题。

以上是关于Razor 页面流畅的验证服务器端不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 VS Code 中调试 Angular Universal Starter App 的服务器端不起作用

使用 Core 2.2 本地化的 Razor 页面不起作用

服务器端应用程序的 Google+ 登录身份验证不起作用

如何从服务器端 Blazor 应用程序中的 Blazor 组件调用 razor 页面而不导致页面刷新

Asp.Net Core Razor 页面中的远程验证

Razor 页面运行时编译不起作用