0

我正在 .net Core 中开发一个新项目,之前一直在使用 .net Framework。

我希望为布尔属性生成 html 选择元素,但使用自定义值而不是 True 和 False(主要是“是”和“否”)。在以前的项目中,我使用了以下方法:

为布尔值创建自定义属性:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class BooleanCustomValuesAttribute : Attribute, IMetadataAware
{
    public string TrueValue { get; set; }
    public string FalseValue { get; set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["TrueValue"] = TrueValue;
        metadata.AdditionalValues["FalseValue"] = FalseValue;
    }
}

在我的模型中使用它:

[BooleanCustomValues(TrueValue = "Yes", FalseValue = "No")]
public bool ThisWorks { get; set; }

然后在编辑器模板中,我可以访问这些值以添加到选择中:

object trueTitle;
ViewData.ModelMetadata.AdditionalValues.TryGetValue("TrueValue", out trueTitle);
trueTitle = trueTitle ?? "True";

object falseTitle;
ViewData.ModelMetadata.AdditionalValues.TryGetValue("FalseValue", out falseTitle);
falseTitle = falseTitle ?? "False";

我现在正尝试在 .net 核心中做类似的事情,这次使用标签助手而不是编辑器模板。

我了解核心不支持按上述方式设置 AdditionalValues?

我找到的最接近的是这个答案: Getting property attributes in TagHelpers

我的标签助手代码看起来像这样 currenty(输出 p 只是为了测试):

public class BooleanSelectTagHelper: TagHelper
    {
        [HtmlAttributeName("asp-for")]
        public ModelExpression Source { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "p";
            output.TagMode = TagMode.StartTagAndEndTag;

            var booleanAttribute = Source.Metadata.ContainerType.GetProperty(Source.Name).GetCustomAttribute(typeof(BooleanCustomValuesAttribute));

            var contents = $@"{booleanAttribute.TrueValue} or {booleanAttribute.FalseValue}";

            output.Content.SetHtmlContent(new HtmlString(contents));
        }
    }

但是我无法让它工作,因为 Source.Metadata.ContainerType.GetProperty(Source.Name).GetCustomAttributes() 返回 null。

令人讨厌的是,在监视窗口中调试和查看 Source.Metadata 时,我可以准确地看到我想在 Source.Metadata.Attributes 下访问的内容——但这似乎不是在调试器之外暴露的东西。

为帖子的长度道歉 - 任何指针都将不胜感激(包括告诉我我做错了!)

4

2 回答 2

0

您的标签助手缺少HtmlTargetElement属性:

[HtmlTargetElement(Attributes = "asp-for")] // <== Add this
public class BooleanSelectTagHelper: TagHelper
{
    [HtmlAttributeName("asp-for")]
    public ModelExpression Source { get; set; }
}

此外,不要忘记_ViewImports.cshtml在 Microsoft 的标签助手之后的文件中导入您自己的标签助手。将“WebApp”替换为包含要添加的标签助手的程序集的名称。阅读更多官方文档

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebApp
于 2020-11-11T22:23:28.947 回答
0

也许这会有所帮助,这是我在创建自定义 TagHelpers 时用来添加属性以进行不显眼验证的方法。您可以将其调整为您想要使用的任何属性。根据我的经验,当您拥有 ModelExpression 的公共成员时,只需将其称为 AspFor,如果没有,它似乎不会获得任何属性。但是,如果名称匹配,那么我永远不会有问题。我目前在 .NET5 上使用它。

public class BooleanSelectTagHelper: TagHelper {
            
    public ModelExpression AspFor { get; set; }
    
    public override void Process(TagHelperContext context, TagHelperOutput output){
        //.. setup excluded for example
         var attribute = this.AspFor
        .Metadata
        .ContainerType
        .GetProperty(AspFor.Name)
        .GetCustomAttributes(typeof(RequiredAttribute), false)                
        .FirstOrDefault();
        if(attribute != null && attribute is RequiredAttribute requiredAttribute) {
            output.MergeAttribute("data-val", "true");
            output.MergeAttribute("data-val-required", requiredAttribute.FormatErrorMessage(AspFor.Name));                
        }
        //.. code to display excluded for example
    }
}

我通常尝试获取属性,然后进行空检查并使用“as”语句在 if 语句中进行强制转换。然后在 if 语句中访问您需要的任何内容。

于 2021-03-17T14:17:43.013 回答