【问题标题】:Change the default ErrorMessage of model validation attribute asp.net core 3.1更改模型验证属性asp.net core 3.1的默认ErrorMessage
【发布时间】:2020-07-21 11:22:13
【问题描述】:

如何避免每次都写[Required(ErrorMessage="My custom error message")],并为整个项目设置默认ErrorMessage

【问题讨论】:

  • 您可以使用包含"My custom error message" 的静态公共属性创建一个新的公共类。但是,您需要在任何地方设置 [Required(ErrorMessage=class.property")],但这是对字符串的改进。

标签: c# asp.net-core .net-core asp.net-core-3.1


【解决方案1】:

如何避免写 [Required(ErrorMessage="My custom error message")] 每次并为整个设置默认的 ErrorMessage 项目?

你可以创建custom attributes来自动生成错误信息,但是你不可避免地需要给对应的字段添加属性来表示你对字段的约束。


更新

如果您有多个不同的验证要求,那么您可以将它们合并到一个自定义属性中,并继承ValidationAttribute 类。

前提是你需要传递参数来区分它们

这是一个案例:

public class CustomRequired : ValidationAttribute
    {
        public CustomRequired(string sepcialType)
        {
            this.SepcialType = sepcialType;
        }
        public string SepcialType { get; private set; }  

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            string errorType;
            if (value == null)
            {
                errorType = "required"; 
            }
            else if (!string.IsNullOrEmpty(SepcialType) && !IsValidEmail(value.ToString()))
            {
                errorType = "not valid";
            }
            else
            {
                return ValidationResult.Success;
            }
            ErrorMessage = $"{validationContext.DisplayName}  field is {errorType}.";
            return new ValidationResult(ErrorMessage);
        }
        bool IsValidEmail(string email)
        {
            try
            {
                var addr = new System.Net.Mail.MailAddress(email);
                return addr.Address == email;
            }
            catch
            {
                return false;
            }
        }
    }
  

类:

 public class ThemTest
    {
        public int Id { get; set; }
        [CustomRequired("")]
        public string Name { get; set; }
        [CustomRequired("")]
        public string Theme { get; set; }
        [CustomRequired("Email")]
        public string Email { get; set; }
    }

验证视图:

@model ThemTest
@{
    ViewData["Title"] = "TestAttr";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>TestAttr</h1>
<form method="post">
    <div class="form-row">
        <label asp-for="Name"></label>
        <input asp-for="Name" type="text" class="form-control" />
        <span asp-validation-for="Name" class="field-validation-valid text-danger"></span>
    </div>
    <div class="form-row">
        <label asp-for="Theme"></label>
        <input asp-for="Theme" type="text" class="form-control" />
        <span asp-validation-for="Theme" class="field-validation-valid text-danger"></span>
    </div>
    <div class="form-row">
        <label asp-for="Email"></label>
        <input asp-for="Email" type="text" class="form-control" />
        <span asp-validation-for="Email" class="field-validation-valid text-danger"></span>
    </div>
    <input id="Submit1" type="submit" value="submit" class="btn btn-primary" />
</form>

这是测试结果:

【讨论】:

  • 很好的解决方法,但并非所有属性都可以继承。例如,EmailAddressAttribute 不能。
  • @VladislavKosovskikh,我已经更新了我的回复,希望对你有所帮助。
【解决方案2】:

经过一些研究,我找到了使用某种本地化和资源文件的唯一方法。你仍然需要写[Required(ErrorMessage="&lt;Resource Key Goes Here&gt;")]。但是像[Required(ErrorMessage=Class.Property)] 这样只使用常量消息的好处是您可以访问资源文件中的属性变量。

我就是这样做的:

  1. 在根目录下创建一个名为 Resources 的文件夹
  2. Resources 文件夹中创建一个名为 ValidationMessages.cs 的空类
  3. Resources 文件夹中创建一个名为 ValidationMessages.resx 的空文件
  4. 使用 VisualStudio 编辑器编辑 .resx 文件
  5. [StringLength] 属性的示例键、值对:"StringLength","最小长度 {2},最大长度 {1}"
  6. 在模型中使用属性[StringLength(20, MinimumLength = 10, ErrorMessage = "StringLength")]
  7. 将此代码添加到 Startup.cs
    using MyProject.Resources;
    ...
    public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
                .AddDataAnnotationsLocalization(options => {
                    options.DataAnnotationLocalizerProvider = (type, factory) =>
                        factory.Create(typeof(ValidationMessages));
                });
        ...

完成了。

【讨论】:

  • 这似乎不起作用,我什至尝试创建一个自定义 StringLocalizer 以作为 DataAnnotationLocalizerProvider 传递,但它永远不会被调用!
  • 为此,我必须指定 ErrorMessage 键:Required(ErrorMessage = "Required")
【解决方案3】:

这就是我的做法。

在 Startup.cs -> Configure() 中,设置您的异常处理程序中间件:

app.UseExceptionHandler("/Home/Error");

这会将所有异常重定向到主控制器错误方法。 现在为 Home/Error 设置视图模型。

在 ErrorViewModel.cs 中:

public class ErrorViewModel
{
    public string RequestId { get; set; }   
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);    
    public string ExceptionMessage { get; set; }
    public bool ShowExceptionMessage => !string.IsNullOrEmpty(ExceptionMessage);
}

在 HomeController 中:

[AllowAnonymous]
public IActionResult Error()
{
    ErrorViewModel errorViewModel = new ErrorViewModel();
    errorViewModel.RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

    string message = "your message";
    errorViewModel.ExceptionMessage = message;
    _logger.LogError(message);
    return View(errorViewModel);
}

此时,您可以在错误视图页面的模型中访问您的自定义错误消息。

【讨论】:

  • 我不使用视图。我实际上有一个 api 服务器。另外,我需要为模型的每个属性提供单独的消息。看不出它有什么帮助。
  • API 服务器应该仍然以相同的方式工作。将异常路由到带有中间件的错误控制器,然后在错误控制器中对属性执行 switch case 并返回该属性的自定义消息。请访问此链接:docs.microsoft.com/en-us/aspnet/core/web-api/…
猜你喜欢
  • 1970-01-01
  • 2012-03-21
  • 2011-09-29
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
相关资源
最近更新 更多