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源码没找到原因,卡了好几天了
建议试试将 [Display(Name = "标题")]
中的 Name 改为不同的名称
[Display(Name = "标题")]
你是指将Name的值改掉还是什么?
@远扬: 改掉,比如[Display(Name = "标题2")]
@dudu: 这个应该不会和DisplayAttribute
有关吧?
客户端验证规则应该是ValidationAttribute
提供的
@dudu: 试过了~无效~字段名为Title
就无法生成验证属性,醉了....
@远扬: 删除 <editor asp-for="Name" asp-required="true" />
试试,是不是不支持多个 <editor>
@dudu: 是支持的~就是因为单个字段名为Title
无效,所以我才多一个Name
作为比较的,只要字段名不为 Title
就会添加客户端验证属性,服务端验证是没问题的。
@远扬: 能提供重现这个问题的示例代码吗?
@dudu: 我试过在nopCommerce上使用也是无效的,但使用asp.net core内置的InputTagHelper
是会生成客户端验证属性的,使用TemplateBuilder
创建自定义TagHelper则在字段名为Title
就不会生成客户端验证属性,字段名为其他均可以(暂时没试出不可以的),稍等为整理下上传问题代码
@dudu:这是问题示例代码: https://files.cnblogs.com/files/chen8854/Sample.rar
感觉应该是.net core的bug
@远扬: 找到原因了,是和 ViewData["Title"] = "Editor Sample";
中的 Title
名称冲突了
@dudu: 尴尬了,名称冲突了,除了将ViewData["Title"]
中的Title
改掉是否还有其他方法处理此问题?
@远扬: 新建一个 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: 谢谢