对所有无效属性使用单个错误消息模板

Use single error message template for all invalid properties

想象一个 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

编辑:

例如,在视图中显示错误之前,像这样更改错误消息:

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

您可以使用验证摘要(请参阅: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; }

I know I can use ErrorMessage for each of them separately, but its not logical! is there any short way to show a specific massage for all of invalid ModelStates?

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

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

如果不想使用上述方法,也可以从ModelState字典中获取无效字段,然后,re-generate报错信息。代码如下:

    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 获取客户端验证结果,然后生成新的错误消息。

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

我创建了一个带有 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);
     }
}

如果您不想对每个 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()));