I'm trying to access my custom attributes like SortableAttribute
attached to my model properties in a T4 Controller template I'm writing. I've copied the class block, assemblies and imports from List.tt as boilerplate.
First I tried to cast the attributes as follows:
<#+
string SortableBy(PropertyInfo property)
{
foreach (object attribute in property.GetCustomAttributes(true))
{
var sortable = attribute as SortableAttribute;
if (sortable != null) return sortable.By == "" ? property.Name : sortable.By;
}
return property.Name;
}
#>
This however yielded no positive results since my project's namespace is unknown to T4. To resolve this, I have added my project's dll and imported the required namespace.
<#@ assembly name ="c:\path\to\MyProject\bin\MyProject.dll" #>
<#@ import namespace= "MyProject.Filters" #>
It seemed to be successful at first (eg. no errors on the namespace import), but it still did not find my attributes. If I replaced SortableAttribute
with MyProject.Filters.SortableAttribute
, the error message was that SortableAttribute
was not found in MyProject.Filters
.
To overcome this, I've changed my code as follows:
<#+
string SortableBy(PropertyInfo property)
{
foreach (object attribute in property.GetCustomAttributes(true))
{
if (attribute != null && attribute.GetType().Name == "SortableAttribute")
{
var sortableBy = (string) attribute.GetType().GetProperty("By").GetValue(attribute, null);
return sortableBy == "" ? property.Name : sortableBy;
}
}
return property.Name;
}
#>
I thought I've hit the jackpot, but I soon had to realise that property.GetCustomAttributes(true)
returns all attributes but not mine...
An example model:
public class MyModel
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[Display(Name = "Full Name")]
[Sortable]
public int Name { get; set; }
}
Implementation of SortableAttribute
:
using System;
namespace MyProject.Filters
{
[AttributeUsage(AttributeTargets.Property)]
public class SortableAttribute : Attribute
{
public SortableAttribute(string by = "")
{
this.By = by;
}
public string By { get; private set; }
}
}
Can you please point me to the right direction?
Any help is greatly appreciated!
Edit:
It turns out that property.GetCustomAttributes(true)
does return my attributes, but the following expression in SortableBy always evaluates to null
:
(string) attribute.GetType().GetProperty("By").GetValue(attribute, null);
Any idea why this can be?
For anyone looking how to do this with MVC5: https://johniekarr.wordpress.com/2015/05/16/mvc-5-t4-templates-and-view-model-property-attributes/
Remember: Build fixes a lot of problems, but REBUILD can fix it all!
To recap and to help others writing T4 templates, here are some working code that can be used as boilerplate:
Reading custom attribute in a .tt file (based on Scaffold() in any default view template):
Model:
Implementation of
SortableAttribute
: