【问题标题】:How to get unobtrusive validation markup in my custom tag helper如何在我的自定义标签助手中获得不显眼的验证标记
【发布时间】:2020-07-04 04:58:32
【问题描述】:

在 ASP.Net Core 自定义标签助手中,是否有一种简单的方法来获取由 <span asp-validation-for="xxx"> 标签助手发出的 HTML 标记?

换句话说,我可以在我的标签助手中获得与HtmlHelper.ValidationMessageFor() 等效的东西吗?还是我需要自己通过挖掘ModelExpression.ModelMetadata 属性来重新创建它?

背景:

我编写了标签助手,它们在常见的 HTML 元素(如 <input><button> 等)周围添加 Bootstrap 标记。除了添加 Bootstrap 标记之外,这些标签助手还在“输入”元素之后添加不显眼的验证标记:

<span class='field-validation-valid' data-valmsg-for='{name}' data-valmsg-replace='true'></span>

这对于客户端验证非常有用,因为 JavaScript 会看到 data-* 属性并执行其操作。 但这不适用于服务器端验证。如果服务器端验证器返回错误消息,则该消息不会显示在表单上。

一个小实验表明&lt;span asp-validation-for="xxx"&gt; 标签助手(我没有使用)与服务器端验证器一起使用,以在相关模型变量出现验证错误时修改发送到客户端的 HTML。修改后的 HTML 包含验证器提供的错误消息:

<span class='field-validation-error' data-valmsg-for='{name}' data-valmsg-replace='true'>Some error message.</span>

所以,我的标签助手需要做同样的事情并发出正常或错误验证消息标记。

如果我的标签助手可以发出 &lt;span asp-validation-for="xxx"&gt; 元素,那将非常简单,但是,据我所知,没有办法将我的标签助手创建的 HTML 解释为标签助手。

我可以挖掘模型元数据并发现错误消息并适当地格式化验证消息&lt;span&gt; 标签,但所有这些工作已经由@987654332 为我完成(而且可能比我做的更正确) @ 和 validation-for span 标签助手。

FWIW,this article 显示了一些允许标签助手访问 HtmlHelper 的魔法。如果可以的话,我宁愿避开这条路,并使用一些闻起来更像原生“标签助手”代码的东西。

【问题讨论】:

    标签: validation tag-helpers asp.net-core-tag-helpers


    【解决方案1】:

    如果您仍然遇到此问题,我可以通过在我自己的 TagHelper 中重新利用现有的 ValidationMessageTagHelper 来实现所需的功能。如果您确保在 ValidationMessageTagHelper 上调用 ProcessAsync 方法,如下所示:

    await validation.ProcessAsync(validationContext, validationOutput);
    

    它将使用来自 ViewData 的服务器端验证创建您期望的验证。 我的用于服务器端验证的自定义验证标签助手看起来像:

    [HtmlTargetElement("validation")]
    public class CustomValidationTagHelper : TagHelper
    {
        private IHtmlGenerator _htmlGenerator;
    
        public CustomValidationTagHelper(IHtmlGenerator htmlGenerator)
        {
            _htmlGenerator = htmlGenerator;
        }
    
        [HtmlAttributeName("asp-for")]
        public ModelExpression For { get; set; }
    
        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }
    
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
    
            var validationContext = CreateTagHelperContext();
            var validationOutput = CreateTagHelperOutput("span");
    
            var validation = new ValidationMessageTagHelper(_htmlGenerator)
            {
                For = For,
                ViewContext = ViewContext,
    
            };
    
            await validation.ProcessAsync(validationContext, validationOutput);
            validationOutput.Attributes.SetAttribute("class", "field-validation-error text-danger");
    
            output.TagName = "";
    
    
            output.Content.AppendHtml(validationOutput);
        }
    
        private static TagHelperContext CreateTagHelperContext()
        {
            return new TagHelperContext(
                new TagHelperAttributeList(),
                new Dictionary<object, object>(),
                Guid.NewGuid().ToString("N"));
        }
    
        private static TagHelperOutput CreateTagHelperOutput(string tagName)
        {
            return new TagHelperOutput(
                tagName,
                new TagHelperAttributeList(),
                (a, b) =>
                {
                    var tagHelperContent = new DefaultTagHelperContent();
                    tagHelperContent.SetContent(string.Empty);
                    return Task.FromResult<TagHelperContent>(tagHelperContent);
                });
        }
    }
    

    并且在页面上像这样使用:

    <validation asp-for="Username" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      相关资源
      最近更新 更多