【问题标题】:Custom data annotations not displaying error on postback - ASP.NET core MVC6自定义数据注释在回发时不显示错误 - ASP.NET 核心 MVC6
【发布时间】:2016-04-13 09:02:30
【问题描述】:

我查看了许多关于此主题的帖子 - 自定义服务器端验证 - hereherehere(我相信这是针对 MVC4),但似乎没有一个为我解决这个问题。

我创建了一个基本的 MVC6 项目(两个文本框)只是为了测试数据注释,但仍然无法使其工作。作为基础,我使用tutorial 并重新创建了他的数据验证类,没有任何更改。

我没有使用实际模型,而是使用 viewModel,如果验证成功,则通过分配给模型来更新数据库。

我对此处的成功验证不感兴趣,但是否在“(ModelState.IsValid)”等于“False”时,它会在文本框下显示错误消息。

我已经单步执行了它,发现它确实单步执行了实际的自定义验证器,并且它肯定在自定义验证中给出了 false 的模型状态 - 返回视图 - 但没有显示错误消息。

但是,如果我从文本框中删除所有内容 - 将其设为空 - 返回视图模型,但这次它会出现红色的“必需”错误。也就是说,错误消息适用于数据注释而不是自定义注释。

好的,所以为什么它显示正常的注释验证错误而不是自定义验证错误

这是 ASP.NET 核心的结果,还是只是我返回视图模型的方式(例如,我更有可能出错)?

我决定包括所有活动部分,因为其中任何一个可能不正确或存在问题。这就是一个模型、一个基于模型的视图模型、一个控制器和按照教程的自定义验证器类。

    public class CompanyDetail
    {
         public int CompanyDetailId { get; set; }
         public string CompanyName { get; set; }
         public string ABN { get; set; }
    }

添加了数据注释的 CompanyDetailViewModel:

 public class CompanyDetailsViewModel
{
    public int CompanyDetailsId { get; set; }

    [ExcludeChar("/")]
    [Required(ErrorMessage = "A Company Name is required")]
    [Display(Name = "Company Name:")]
    [StringLength(100)]
    public string CompanyName { get; set; }

    [Required(ErrorMessage = "An ABN is required")]
    [CheckValidABN(ErrorMessage = "This is not a valid ABN")]
    [Display(Name = "ABN:")]
    public string ABN { get; set; }
}

控制器: 公共类 CompanyDetailsController : 控制器 { 私有 ApplicationDbContext _context;

    public CompanyDetailsController(ApplicationDbContext context)
    {
        _context = context;    
    }


    // GET: CompanyDetailsViewModels/Edit/5
    public IActionResult Edit()
    {

        var Company = _context.CompanyDetails.First();
        if (Company == null)
        {
            return HttpNotFound();
        }
        var CompanyDetails = new CompanyDetailsViewModel();

        CompanyDetails.CompanyDetailsId = Company.CompanyDetailId;
        CompanyDetails.CompanyName = Company.CompanyName;
        CompanyDetails.ABN = Company.ABN;

        return View(CompanyDetails);
    }

    // POST: CompanyDetailsViewModels/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(CompanyDetailsViewModel companyDetailsViewModel)
    {
        if (ModelState.IsValid)
        {
            CompanyDetail Company = _context.CompanyDetails.First();
            var CompanyDetails = new CompanyDetailsViewModel();

            Company.CompanyName = CompanyDetails.CompanyName;
            CompanyDetails.ABN = Company.ABN;

            _context.CompanyDetails.Update(Company);
            _context.SaveChanges();

            return RedirectToAction("Index");
        }
        return View(companyDetailsViewModel);
    }

}

具有(普通脚手架)形式的视图 - 它使用视图模型作为模型:

<form asp-action="Edit">
<div class="form-horizontal">
    <h4>CompanyDetailsViewModel</h4>
    <hr />
    <div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="CompanyDetailsId" />
    <div class="form-group">
        <label asp-for="ABN" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="ABN" class="form-control" />
            <span asp-validation-for="ABN" class="text-danger" />
        </div>
    </div>
    <div class="form-group">
        <label asp-for="CompanyName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="CompanyName" class="form-control" />
            <span asp-validation-for="CompanyName" class="text-danger" />
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>

以及实际的自定义验证类:

public class ExcludeChar : ValidationAttribute
{
    private readonly string _chars;
    public ExcludeChar(string chars)
    : base("{0} contains invalid character.")
    {
        _chars = chars;
    }


    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            for (int i = 0; i < _chars.Length; i++)
            {
                var valueAsString = value.ToString();
                if (valueAsString.Contains(_chars[i]))
                {
                    var errorMessage = FormatErrorMessage(validationContext.DisplayName);
                    return new ValidationResult(errorMessage);
                }
            }
        }
        return ValidationResult.Success;
    }
}

【问题讨论】:

  • 如果我将视图 cshtml 中的“
    ”更改为“ValidationSummary.All”错误消息显示但仅在页面顶部 - 不在文本框下方。如果我清除文本框,则“requred”错误会显示在两个地方......由于某种原因,自定义验证仅显示摘要,并且仅在其设置为“全部”时显示
  • MVC6 是否存在此功能?
  • 您不使用内置的 html 帮助程序是否有特定原因?

标签: asp.net-mvc validation asp.net-core-mvc data-annotations


【解决方案1】:

我在你使用的代码中发现了它

<span asp-validation-for="number" class="text-danger" />

这是 Visual Studio 生成的默认 html(不知道为什么)。您需要添加结束标签。像使用它一样

<span asp-validation-for="number" class="text-danger" ></span>

它会在字段下方显示错误消息。

【讨论】:

    【解决方案2】:

    您需要做的是在视图中指定您希望显示自定义错误消息的位置。

    示例:

    <div>
        @Html.ValidationMessage("CreditRating")
    </div>
    

    然后返回与“成员”CreditRating 相关的 ValidationResult 将显示在视图的该部分中。 member 用引号引起来,因为名称实际上可以是任何名称,不必是不动产的真实名称。

       results.Add(new ValidationResult("NO NO NO", new[] { "CreditRating" }));
    

    我同意这是令人惊讶的行为。我似乎自定义错误的处理方式不同。可能是一些没有记录的命名约定。

    【讨论】:

    • 假设它应该是什么“结果”?
    猜你喜欢
    • 1970-01-01
    • 2016-05-09
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2011-08-05
    相关资源
    最近更新 更多