c# - 验证摘要和错误的自定义格式

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

问题

总结

对于验证摘要,您通常有这样的内容:

<div asp-validation-summary="ModelOnly" class="..."></div>

其中,如果出现空字符串错误,因为字段/属性将显示在 <ul> 内的那个 div 内。列表。

如果我想使用 div 的序列来显示它们怎么办?具有特定的 class属性?或者任何其他自定义格式?

字段验证

对于现场验证,您通常会这样做:

<div class="form-group">
    <label asp-for="OldPassword"></label>
    <input asp-for="OldPassword" class="form-control" />
    <span asp-validation-for="OldPassword" class="text-danger"></span>
</div>

并且错误被作为文本插入到 span 中元素。

我使用的模板需要 has-errors应用于 form-group 的类div元素,以防出现错误,因为它需要同时设置标签和输入的样式。

它还需要 span成为div (出于某些未知原因)并且令人惊讶地改变了 spandiv防止 div 插入错误文本;更不用说包装 spandiv 里面产生的问题是 div应用了适当的间距,因此即使没有错误,div 也会显示令人讨厌的空格。

问题(tl; dr)

使用如上所示的自定义规则处理自定义表单验证格式(尝试 DRY,因为我的应用程序有很多表单)的最惯用的方法是什么?

最佳答案

这里有一些扩展点,您可以考虑为验证摘要和字段验证错误提供自定义呈现:

  • 自定义现有的验证标签助手(注册新的 IHtmlGenerator )
  • 创建新的验证标签助手(注册新的 Tag Helpers)

自定义现有的验证标签助手

asp-validation-summary asp-validation-for 标签助手使用 GenerateValidationSummaryGenerateValidationMessage IHtmlGenerator 的注册实现方法服务 DefaultHtmlGenerator 默认情况下。

您可以提供派生 DefaultHtmlGenerator 的自定义实现并覆盖这些方法,然后在启动时注册服务。这样,这些标签助手将使用您的自定义实现。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddTransient<IHtmlGenerator, MyHtmlGenerator>();
}

这是 source code of DefaultHtmlGenerator 的链接帮助您自定义实现。

示例 - 创建新的实现 IHtmlGenerator

这只是一个简单的示例,用于显示所需的命名空间和方法,以及可以进入您的自定义实现的内容。提供自定义实现后,不要忘记在 ConfigureServices 中注册它就像我上面所做的那样。

using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;

namespace ValidationSampleWebApplication
{
    public class MyHtmlGenerator : DefaultHtmlGenerator
    {
        public MyHtmlGenerator(IAntiforgery antiforgery, IOptions<MvcViewOptions> optionsAccessor, IModelMetadataProvider metadataProvider, IUrlHelperFactory urlHelperFactory, HtmlEncoder htmlEncoder, ValidationHtmlAttributeProvider validationAttributeProvider) 
            : base(antiforgery, optionsAccessor, metadataProvider, urlHelperFactory, htmlEncoder, validationAttributeProvider)
        {
        }
        public override TagBuilder GenerateValidationMessage(ViewContext viewContext, ModelExplorer modelExplorer, string expression, string message, string tag, object htmlAttributes)
        {
            return base.GenerateValidationMessage(viewContext, modelExplorer, expression, message, tag, htmlAttributes);
        }
        public override TagBuilder GenerateValidationSummary(ViewContext viewContext, bool excludePropertyErrors, string message, string headerTag, object htmlAttributes)
        {
            return base.GenerateValidationSummary(viewContext, excludePropertyErrors, message, headerTag, htmlAttributes);
        }
    }
}

创建新的验证标签助手

您也可以 author your custom tag helpers .为此,从 TagHelper 派生就足够了并覆盖 Process方法。

然后您可以简单地在 View 中或在_ViewImports.cshtml 中全局注册创建的标签助手。 :

@using ValidationSampleWebApplication
@using ValidationSampleWebApplication.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, ValidationSampleWebApplication

此外,在创建用于验证的自定义标签助手时,您可以考虑:

  • 从头开始创建验证标签助手
  • 从现有的标签助手类驱动

示例 - 将 hasError 类添加到表单组 div

在这个例子中,我创建了一个 asp-myvalidation-for可应用于 div这样的元素<div class="form-group" asp-myvalidation-for="LastName">并将添加 hasError类别为 div如果指定字段有验证错误。不要忘记在_ViewImports.cshtml中注册它就像我上面所做的那样。

using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace ValidationSampleWebApplication
{
    [HtmlTargetElement("div", Attributes = MyValidationForAttributeName)]
    public class MyValidationTagHelper : TagHelper
    {
        private const string MyValidationForAttributeName = "asp-myvalidation-for";

        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }

        [HtmlAttributeName(MyValidationForAttributeName)]
        public ModelExpression For { get; set; }
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            base.Process(context, output);
            ModelStateEntry entry;
            ViewContext.ViewData.ModelState.TryGetValue(For.Name, out entry);
            if (entry != null && entry.Errors.Count > 0)
            {
                var builder = new TagBuilder("div");
                builder.AddCssClass("hasError");
                output.MergeAttributes(builder);   
            }
        }
    }
}

示例 - 添加 field-validation-error类到表单组 div

在下面的示例中,我添加了 div支持标准asp-validation-for标签助手。现有的标签助手只支持 div 元素。我在这里添加了 div支持asp-validation-for标签助手,如果出现错误,它将添加 field-validation-error否则,在有效情况下 div会有field-validation-valid类。

标签的默认行为是,如果标签有内容,它不会对标签的内容进行任何更改。因此,将标签助手添加到一个空的 span将向 span 添加验证错误,但对于具有某些内容的 div,它只是更改 div 的类。不要忘记在_ViewImports.cshtml中注册它就像我上面所做的那样。

using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.TagHelpers;

namespace ValidationSampleWebApplication
{
    [HtmlTargetElement("div", Attributes = ValidationForAttributeName)]
    public class MytValidationMessageTagHelper : ValidationMessageTagHelper
    {
        private const string ValidationForAttributeName = "asp-validation-for";
        public MytValidationMessageTagHelper(IHtmlGenerator generator) : base(generator)
        {
        }
    }
}

关于c# - 验证摘要和错误的自定义格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46800600/

相关文章:

c# - DateTime.TryParseExact() 拒绝有效格式

c# - 在 Debug模式下单步执行时 GUI 不会重绘

asp.net - 在 ASP.NET 和 Javascript 中使用复选框

c# - PayPal 即时付款通知 (IPN) 不工作 ASP.NET C#

c# - 如何从IsolatedStorageSettings(WP8.0)迁移到ApplicationData(WP8.1运行时)

c# - 从父级调用特定 MDI 子级的方法

c# - 页面正在加载但未渲染 style.css

c# - WebRequest.GetResponse() 在几次请求后超时

c# - DataGrid AutoGenerateColumns ="True"- 如何追加一列?

c# - WPF TextBox 在焦点上更改颜色