客製化 TagHelper 是 Asp.net Core 一個很重要的擴充,允許我們非常方便的建立各種彈性的運用。另外一方面在 Model 中如何定義好屬性(Property),也有相當一部分要透過 Attribute 擴充我們的定義。
以下定義一個 Attribute 用途只為了標註在特定屬性中,可以對應的代碼:
[AttributeUsage(AttributeTargets.Property)]
public class DropdownAttribute : Attribute
{
public string CodeMap { get; set; }
public DropdownAttribute(string code)
{
this.CodeMap = code;
}
}
使用方式很簡單,直接在物件中的屬性加入此 Attribute 就可以指定代碼:
public class DailyReportItem
{
public int Visitors { get; set; }
[Required]
[Dropdown("DailyProgress")]
public string Progress { get; set; }
}
現在我們希望可以自訂 TagHelper,用來處理 Required attribute 的內容(上面範例的 DailyProgress)。在轉寫自訂義的 TagHelper,只有一點需要注意:HtmlAttributeName 要使用 ModelExpression 型態,不可以用 String。這裡最大差別在於如果指定 String 則 razor 會傳入值,而非物件本身;但我們需要物件本身用來解析屬性值。
程式碼如下:
public class CustomerTagHelper: 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 contents = $@"
Model name: {Source.Metadata.ContainerType.FullName}<br/>
Property name: {Source.Name}<br/>
Current Value: {Source.Model}<br/>
Is Required: {Source.Metadata.IsRequired}";
output.Content.SetHtmlContent(new HtmlString(contents));
}
}
其中 IsRequired 就是代表是否有宣告 required attribute。使用方式跟一般宣告一樣:
<customer asp-for="Name"></customer>
如果需要處理 Dropdown attributte,可以用 MetaData 取出客製化的屬性:
var dropdown = model.Metadata.ContainerType.GetProperty(code)
.GetCustomAttributes()
.OfType<DropdownAttribute>().FirstOrDefault();