首页 新闻 会员 周边 捐助

asp.net core taghelper无法生成客户端验证属性

0
悬赏园豆:50 [已解决问题] 解决于 2019-02-01 17:03

EditorTagHelper.cs (来源:nopCommerce中的nop-editor)

[HtmlTargetElement("editor", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)]
    public class EditorTagHelper : TagHelper {
        private const string ForAttributeName = "asp-for";
        private const string DisabledAttributeName = "asp-disabled";
        private const string RequiredAttributeName = "asp-required";
        private const string RenderFormControlClassAttributeName = "asp-render-form-control-class";
        private const string TemplateAttributeName = "asp-template";
        private const string PostfixAttributeName = "asp-postfix";

        private readonly IHtmlHelper _htmlHelper;

        [HtmlAttributeName(ForAttributeName)]
        public ModelExpression For { get; set; }

        [HtmlAttributeName(DisabledAttributeName)]
        public string IsDisabled { set; get; }

        [HtmlAttributeName(RequiredAttributeName)]
        public string IsRequired { set; get; }

        [HtmlAttributeName(RenderFormControlClassAttributeName)]
        public string RenderFormControlClass { set; get; }

        [HtmlAttributeName(TemplateAttributeName)]
        public string Template { set; get; }

        [HtmlAttributeName(PostfixAttributeName)]
        public string Postfix { set; get; }

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

        public EditorTagHelper(IHtmlHelper htmlHelper) {
            _htmlHelper = htmlHelper;
        }

        public override void Process(TagHelperContext context, TagHelperOutput output) {
            if (context == null) {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null) {
                throw new ArgumentNullException(nameof(output));
            }

            output.SuppressOutput();

            var htmlAttributes = new Dictionary<string, object>();

            bool.TryParse(IsDisabled, out var disabled);
            if (disabled) {
                htmlAttributes.Add("disabled", "disabled");
            }

            bool.TryParse(IsRequired, out var required);
            if (required) {
                output.PreElement.SetHtmlContent("<div class=\"input-group input-group-required\">");
                output.PostElement.SetHtmlContent("<div class=\"input-group-btn\"><span class=\"required\">*</span></div></div>");
            }

            var viewContextAware = _htmlHelper as IViewContextAware;
            viewContextAware?.Contextualize(ViewContext);

            bool.TryParse(RenderFormControlClass, out var renderFormControlClass);
            if (string.IsNullOrEmpty(RenderFormControlClass) && For.Metadata.ModelType.Name.Equals("String") || renderFormControlClass)
                htmlAttributes.Add("class", "form-control");

            if (For.Metadata.AdditionalValues.TryGetValue("PlaceHolderAttribute", out var value)) {
                if (value is PlaceHolderAttribute placeholder) {
                    var content = placeholder.Content;
                    htmlAttributes.Add("placeholder", content);
                }
            }

            var viewEngine = CommonHelper.GetPrivateFieldValue(_htmlHelper, "_viewEngine") as IViewEngine;
            var bufferScope = CommonHelper.GetPrivateFieldValue(_htmlHelper, "_bufferScope") as IViewBufferScope;

            var templateBuilder = new TemplateBuilder(
                viewEngine,
                bufferScope,
                _htmlHelper.ViewContext,
                _htmlHelper.ViewData,
                For.ModelExplorer,
                For.Name,
                Template,
                readOnly: false,
                additionalViewData: new { htmlAttributes, postfix = this.Postfix });

            var htmlOutput = templateBuilder.Build();
            output.Content.SetHtmlContent(htmlOutput.RenderHtmlContent());
        }
    }

 SampleModel.cs

复制代码
public class SampleModel {
        [Display(Name = "标题")]
        [PlaceHolder("请提供标题")]
        [Required(ErrorMessage = "请输入主题")]
        [MaxLength(100,ErrorMessage = "太多字了")]
        public string Name { get; set; }

        [Display(Name = "标题")]
        [PlaceHolder("请提供标题")]
        [Required(ErrorMessage = "请输入主题")]
        [MaxLength(100, ErrorMessage = "太多字了")]
        public string Title { get; set; }
    }
复制代码

cshtml

@model SampleModel
<editor asp-for="Name" asp-required="true" />
<editor asp-for="Title" asp-required="true" />

Name可以生成验证属性

Title无法生成验证属性

奇怪了,查了asp.net core源码没找到原因,卡了好几天了

远扬的主页 远扬 | 初学一级 | 园豆:30
提问于:2019-01-31 17:29
< >
分享
最佳答案
0

建议试试将 [Display(Name = "标题")] 中的 Name 改为不同的名称

收获园豆:50
dudu | 高人七级 |园豆:31033 | 2019-01-31 17:45

[Display(Name = "标题")]你是指将Name的值改掉还是什么?

远扬 | 园豆:30 (初学一级) | 2019-01-31 20:27

@远扬: 改掉,比如[Display(Name = "标题2")]

dudu | 园豆:31033 (高人七级) | 2019-01-31 20:38

@dudu: 这个应该不会和DisplayAttribute有关吧?

客户端验证规则应该是ValidationAttribute提供的

远扬 | 园豆:30 (初学一级) | 2019-02-01 07:22

@dudu: 试过了~无效~字段名为Title就无法生成验证属性,醉了....

远扬 | 园豆:30 (初学一级) | 2019-02-01 08:48

@远扬: 删除 <editor asp-for="Name" asp-required="true" /> 试试,是不是不支持多个 <editor>

dudu | 园豆:31033 (高人七级) | 2019-02-01 11:17

@dudu: 是支持的~就是因为单个字段名为Title无效,所以我才多一个Name作为比较的,只要字段名不为 Title 就会添加客户端验证属性,服务端验证是没问题的。

远扬 | 园豆:30 (初学一级) | 2019-02-01 14:51

@远扬: 能提供重现这个问题的示例代码吗?

dudu | 园豆:31033 (高人七级) | 2019-02-01 15:15

@dudu: 我试过在nopCommerce上使用也是无效的,但使用asp.net core内置的InputTagHelper是会生成客户端验证属性的,使用TemplateBuilder创建自定义TagHelper则在字段名为Title就不会生成客户端验证属性,字段名为其他均可以(暂时没试出不可以的),稍等为整理下上传问题代码

远扬 | 园豆:30 (初学一级) | 2019-02-01 15:26

@dudu:这是问题示例代码: https://files.cnblogs.com/files/chen8854/Sample.rar

感觉应该是.net core的bug

远扬 | 园豆:30 (初学一级) | 2019-02-01 15:46

@远扬: 找到原因了,是和 ViewData["Title"] = "Editor Sample"; 中的 Title 名称冲突了

dudu | 园豆:31033 (高人七级) | 2019-02-01 16:38

@dudu: 尴尬了,名称冲突了,除了将ViewData["Title"]中的Title改掉是否还有其他方法处理此问题?

远扬 | 园豆:30 (初学一级) | 2019-02-01 16:45

@远扬: 新建一个 ViewData ,移除 Title ,传给 TemplateBuilder

var viewData = new ViewDataDictionary(_htmlHelper.ViewData);
viewData.Remove("Title");
var templateBuilder = new TemplateBuilder(
    viewEngine,
    bufferScope,
    _htmlHelper.ViewContext,
    viewData,
    For.ModelExplorer,
    For.Name,
    Template,
    readOnly: false,
    additionalViewData: new { htmlAttributes, postfix = this.Postfix });
dudu | 园豆:31033 (高人七级) | 2019-02-01 16:55

@dudu: 谢谢

远扬 | 园豆:30 (初学一级) | 2019-02-01 17:03
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册