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

Sho*_*hoe 8 .net c# asp.net .net-core asp.net-core

问题

摘要

对于验证摘要,您通常会遇到以下情况:

<div asp-validation-summary="ModelOnly" class="..."></div>
Run Code Online (Sandbox Code Playgroud)

如果有空字符串的错误,则字段/属性将显示在<ul>列表中的div内.

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

现场验证

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

<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>
Run Code Online (Sandbox Code Playgroud)

并将错误作为文本插入span元素中.

我正在使用一个模板,需要将has-errors类应用于form-group div元素以防有错误,因为它需要设置标签和输入的样式.

它还要求span是一个div(一些未知的原因)和令人惊讶的是改变spandiv阻止在div从插入错误的文本; 更不用说包裹span 内部div产生一个问题,即div适当的间距应用于它,所以即使没有错误,div显示一个恼人的空间.

问题(tl; dr)

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

Rez*_*aei 9

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

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

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

asp-validation-summaryasp-validation-for标记帮助程序使用 GenerateValidationSummary和默认情况下GenerateValidationMessage已注册的IHtmlGenerator服务实现的方法DefaultHtmlGenerator.

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddTransient<IHtmlGenerator, MyHtmlGenerator>();
}
Run Code Online (Sandbox Code Playgroud)

以下是帮助您自定义实现的源代码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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

创建新的验证标记帮助程序

您还可以编写自定义标记帮助程序.要做到这一点,就足以从方法中获取TagHelper并覆盖它们Process.

然后,您只需在视图中或全局注册已创建的标记助手_ViewImports.cshtml:

@using ValidationSampleWebApplication
@using ValidationSampleWebApplication.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, ValidationSampleWebApplication
Run Code Online (Sandbox Code Playgroud)

此外,在创建自定义标记帮助程序以进行验证时,您可以考虑:

  • 从头开始创建验证标记助手
  • 从现有的tag-helper类驱动

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

在这个例子中,我创建了一个asp-myvalidation-for可以以div这种方式应用于元素的方法,<div class="form-group" asp-myvalidation-for="LastName">并且如果指定的字段有验证错误,则会添加hasErrordiv.不要忘记_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);   
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

示例 - 将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)
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)