【问题标题】:Use single error message template for all invalid properties对所有无效属性使用单个错误消息模板
【发布时间】:2020-10-12 08:42:02
【问题描述】:

想象一个razor page 和一个Form 有许多用户填写它们的输入。

当它想要像这样验证发布的模型时使用post 方法:

public IActionResult OnPost()
{
     if (!ModelState.IsValid)
     {
        return Page(model);
     }
}

例如,如果该模型的 3 个属性(名称:a、b、c)无效,它会返回剃刀视图并显示错误(因为每个属性都有asp-validation-for),如下所示:

The a field is required.
The b field is not a valid e-mail address.
The c field is required.

我想为所有人显示一个特定的错误,如下所示:

This Input is not valid.
This Input is not valid.
This Input is not valid.

我知道我可以分别为它们中的每一个使用(ErrorMessage =""),但它在大尺寸上不合逻辑!有没有办法为所有无效的ModelStates 显示特定的按摩?

编辑:

例如,在 View 中显示错误之前,将其错误消息更改如下:

@foreach (var error in modelStateErrors)
{
    error.text = "Fill it";
}

【问题讨论】:

    标签: asp.net asp.net-core razor-pages modelstate jquery-form-validator


    【解决方案1】:

    我使用 ModelState 的扩展方法创建了一个解决方案。
    它基本上会从状态中删除任何错误,并将它们与所需的消息一起添加回来。

    在你的命名空间中创建一个ModelStateExtensions.cs

    public static class ModelStateExtensions
    {
        public static void SetAllErrorMessages(this ModelStateDictionary modelState, string errorMessage)
        {
            foreach (var state in modelState)
            {
                if (state.Value.Errors.Count > 0)
                {
                    modelState.Remove(state.Key);
                    modelState.AddModelError(state.Key, errorMessage);
                }
            }
        }
    }
    

    如果你的 ModelState 无效,你可以在返回页面之前转换消息:

    public IActionResult OnPost()
    {
         if (!ModelState.IsValid)
         {
            ModelState.SetAllErrorMessages("Your message here");
            return Page(model);
         }
    }
    

    【讨论】:

      【解决方案2】:

      我知道我可以分别对它们中的每一个使用 ErrorMessage,但它不是 合乎逻辑!是否有任何简短的方法可以为所有人显示特定的按摩 无效的模型状态?

      对于这个问题,我认为最简单的显示错误信息的方法是使用ErrorMessage,如果你想同时显示它们,你可以使用asp-validation-summary属性,像这样:

      <div asp-validation-summary="All" class="text-danger"></div>

      如果您不想使用上述方法,您也可以从 ModelState 字典中获取无效字段,然后重新生成错误消息。代码如下:

          public IActionResult OnPostAsync()
          {
              if (!ModelState.IsValid)
              {
                  //get the new error message, you could also get all inValid fields.
                  var messages = ModelState.Keys
                          .SelectMany(key => ModelState[key].Errors.Select(x => string.Format("The {0} is invalid", key)))
                          .ToList();
                  ViewData["message"] = messages; //transfer the error message to the view
      
                  return Page();
              }
               return  RedirectToPage("./Index");
            }
      

      查看代码(显示错误信息(不使用asp-validation-forasp-validation-summary)):

              <div class="form-group">
                  @if (ViewData["message"] != null)
                  {
                      foreach (var item in (List<string>)ViewData["message"])
                      { 
                          <span class="text-danger">@item</span><br/>
                      }
                  }
                  <div id="debug">
      
                  </div>
              </div>
      

      输出如下:

      【注意】以上方法为服务端验证。如果您想使用客户端验证来实现相同的行为,则必须使用 JavaScript 获取客户端验证结果,然后生成新的错误消息。

      所以,在我看来,我建议您可以尝试使用第一种方法(使用错误消息和asp-validation-summary)来显示错误消息,并通过使用每个属性分隔符的错误消息,用户可以更容易了解验证规则。

      【讨论】:

        【解决方案3】:

        如果您不想更改每个 Razor 页面,可以使用页面过滤器自动清除和重命名错误消息。

        这是一个页面过滤器示例:

        public class ModelStatePageFilter : IPageFilter
        {
            public void OnPageHandlerExecuted(PageHandlerExecutedContext ctx) { }
        
            public void OnPageHandlerExecuting(PageHandlerExecutingContext ctx)
            {
                foreach (var (k, v) in ctx.ModelState
                    .Where(x => x.Value.ValidationState == ModelValidationState.Invalid))
                {
                    v.Errors.Clear();
                    v.Errors.Add("This Input is not valid.");
                }
            }
        
            public void OnPageHandlerSelected(PageHandlerSelectedContext ctx) { }
        }
        

        您需要在Startup.ConfigureServices 中注册此页面过滤器。以下是如何做到这一点的示例:

        services.AddRazorPages()
            .AddMvcOptions(o => o.Filters.Add(new ModelStatePageFilter()));
        

        【讨论】:

          【解决方案4】:

          您可以使用验证摘要(请参阅:https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-validation-tag-helpers)。

          @model RegisterViewModel
          
          <form asp-controller="Demo" asp-action="RegisterValidation" method="post">
              <div asp-validation-summary="ModelOnly"></div>
              Email:  <input asp-for="Email" /> <br />
              <span asp-validation-for="Email"></span><br />
              Password: <input asp-for="Password" /><br />
              <span asp-validation-for="Password"></span><br />
              <button type="submit">Register</button>
          </form>
          

          如果您想更改显示的错误消息,可以在您的 ViewModel 中进行:

          [Required(ErrorMessage = "This Input is invalid")]
          public string Email { get; set; }
          
          [Required(ErrorMessage = "This Input is invalid")]
          public string Password{ get; set; }
          

          【讨论】:

          • 感谢您的回答,但我想分别显示每个无效输入的特定错误,以向用户显示哪个输入不正确,但不是一个错误!
          • 在上面的代码中,如果您的邮箱和密码都有错误,您将照常显示验证错误(span asp-validation-for),另外,这两个错误也会显示在表格顶部(div asp-validation-summary 所在的位置)。它不会只显示一个错误,而是两个错误都显示两次。
          猜你喜欢
          • 1970-01-01
          • 2018-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多