изменить шаблон TT, чтобы добавить необходимый элемент HTML - PullRequest
0 голосов
/ 24 февраля 2011

Я пытаюсь создать шаблон t4, чтобы ускорить мой шаблон создания формы.

Можно ли добавить дополнительный HTML в зависимости от того, требуется ли свойство модели? например,

  [Required]
  [Display(Name = "Contact Email Address:")]
  public string ContactEmailAddress { get; set; }

Теперь в моем файле tt сделайте что-то вроде

foreach (ModelProperty property in GetModelProperties(mvcHost.ViewDataType)) {
if (!property.IsPrimaryKey && !property.IsReadOnly) {
 #>
    <div>
        @Html.LabelFor(model => model.<#= property.Name #>)
        @Html.EditorFor(model => model.<#= property.Name #>)
        @Html.ValidationMessageFor(model => model.<#= property.Name #>)
        if(this.Required==true){<span class="required-field"></span>}
    </div>
<#
}

Или это невозможно?

Ответы [ 4 ]

1 голос
/ 06 сентября 2013

1, Открыть этот файл:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcViewWithContextScaffolder\ModelPropertyFunctions.include.t4

2, добавить свойство в ModelProperty

class ModelProperty {
    public string Name { get; set; }
    public string AssociationName { get; set; }
    public string ValueExpression { get; set; }
    public string ModelValueExpression { get; set; }
    public string ItemValueExpression { get; set; }
    public EnvDTE.CodeTypeRef Type { get; set; }
    public bool IsPrimaryKey { get; set; }
    public bool IsForeignKey { get; set; }//
    public bool IsReadOnly { get; set; }//
    public bool IsRequired{ get; set;}//Here is your customer Property
    public bool Scaffold { get; set; }
}

3, добавить метод под этот класс

bool IsRequired(EnvDTE.CodeProperty propertyType)
{
    foreach (EnvDTE.CodeAttribute attribute in propertyType.Attributes) 
    {
        if (String.Equals(attribute.FullName, "System.ComponentModel.DataAnnotations.RequiredAttribute", StringComparison.Ordinal))
        {
            return true;
        }
    }
    return false;
}

4, перейдите в конец этого файла, чтобы изменить метод GetElptableProperties:

List<ModelProperty> GetEligibleProperties(EnvDTE.CodeType typeInfo) {
    List<ModelProperty> results = new List<ModelProperty>();
    if (typeInfo != null) {
        foreach (var prop in typeInfo.GetPublicMembers().OfType<EnvDTE.CodeProperty>()) {
            if (prop.HasPublicGetter() && !prop.IsIndexerProperty() && IsBindableType(prop.Type)) {
                string valueExpression = GetValueExpressionSuffix(prop);

                results.Add(new ModelProperty {
                    Name = prop.Name,
                    AssociationName = GetAssociationName(prop),
                    ValueExpression = valueExpression,
                    ModelValueExpression = "Model." + valueExpression,
                    ItemValueExpression = "item." + valueExpression,
                    Type = prop.Type,
                    IsPrimaryKey = IsPrimaryKey(prop),
                    IsForeignKey = IsForeignKey(prop),
                    IsRequired=IsRequired(prop),//Here is your customer property.
                    IsReadOnly = !prop.HasPublicSetter(),
                    Scaffold = Scaffold(prop)
                });
            }
        }
    }

    return results;
}

5, перейти к файлу

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates\MvcViewWithContextScaffolder\Edit.cs.t4

Добавьте следующую проверку перед вашим ValidationMessageFor

@Html.ValidationMessageFor(model => model.<#= property.Name #>):

Коды вроде этого:

<#
            if (property.IsRequired) {
#>
    *<!--your html code-->
<#
            }
#>
0 голосов
/ 16 мая 2015

Шаблоны T4 изменились с MVC5.Чтобы выполнить это в MVC5, я написал учебник здесь: https://johniekarr.wordpress.com/2015/05/16/mvc-5-t4-templates-and-view-model-property-attributes/

0 голосов
/ 25 января 2012

Если кто-то все еще ищет решение ...

Я использую атрибут MetadataType для определения атрибутов свойств, таких как Required или DisplayName в отдельном классе.Пример:

[MetadataType(typeof(personMetaData))]
public partial class Person
{

}

public class personMetaData
{
    [DisplayName("Surname")]
    [Required]
    public object Name { get; set; }
}

Если вы хотите получить доступ к этим атрибутам в шаблоне t4, вы должны расширить класс ModelProperty и создатель в файле шаблона.

Поместите следующий код внижней части вашего шаблона (например, List.tt).Вы должны заменить существующий код.

<#+
// Describes the information about a property on the model
public class ModelProperty
{
    public string Name { get; set; }
    public string ValueExpression { get; set; }
    public Type UnderlyingType { get; set; }
    public bool IsPrimaryKey { get; set; }
    public bool IsReadOnly { get; set; }
    public string DisplayName { get; set; }
}

// Change this list to include any non-primitive types you think should be eligible for display/edit
private static Type[] bindableNonPrimitiveTypes = new[]
                                                      {
                                                          typeof (string),
                                                          typeof (decimal),
                                                          typeof (Guid),
                                                          typeof (DateTime),
                                                          typeof (DateTimeOffset),
                                                          typeof (TimeSpan),
                                                      };

// Call this to get the list of properties in the model. Change this to modify or add your
// own default formatting for display values.
public  List<ModelProperty> GetModelProperties(Type type)
{
    List<ModelProperty> results = GetEligibleProperties(type);

    foreach (ModelProperty prop in results)
    {
        if (prop.UnderlyingType == typeof (double) || prop.UnderlyingType == typeof (decimal))
        {
            prop.ValueExpression = "String.Format(\"{0:F}\", " + prop.ValueExpression + ")";
        }
        else if (prop.UnderlyingType == typeof (DateTime))
        {
            prop.ValueExpression = "String.Format(\"{0:g}\", " + prop.ValueExpression + ")";
        }
    }

    return results;
}

// Call this to determine if the property represents a primary key. Change the
// code to change the definition of primary key.
private bool IsPrimaryKey(PropertyInfo property)
{
    if (string.Equals(property.Name, "id", StringComparison.OrdinalIgnoreCase))
    {
        // EF Code First convention
        return true;
    }

    if (string.Equals(property.Name, property.DeclaringType.Name + "id", StringComparison.OrdinalIgnoreCase))
    {
        // EF Code First convention
        return true;
    }

    foreach (object attribute in property.GetCustomAttributes(true))
    {
        if (attribute is KeyAttribute)
        {
            // WCF RIA Services and EF Code First explicit
            return true;
        }

        var edmScalar = attribute as EdmScalarPropertyAttribute;
        if (edmScalar != null && edmScalar.EntityKeyProperty)
        {
            // EF traditional
            return true;
        }

       /* var column = attribute as ColumnAttribute;
        if (column != null && column.IsPrimaryKey)
        {
            // LINQ to SQL
            return true;
        }*/
    }

    return false;
}

// This will return the primary key property name, if and only if there is exactly
// one primary key. Returns null if there is no PK, or the PK is composite.
private string GetPrimaryKeyName(Type type)
{
    IEnumerable<string> pkNames = GetPrimaryKeyNames(type);
    return pkNames.Count() == 1 ? pkNames.First() : null;
}

// This will return all the primary key names. Will return an empty list if there are none.
private IEnumerable<string> GetPrimaryKeyNames(Type type)
{
    return GetEligibleProperties(type).Where(mp => mp.IsPrimaryKey).Select(mp => mp.Name);
}

// Helper
private List<ModelProperty> GetEligibleProperties(Type type)
{
    List<ModelProperty> results = new List<ModelProperty>();

    foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
        if (prop.GetGetMethod() != null && prop.GetIndexParameters().Length == 0 &&
            IsBindableType(underlyingType))
        {
            var displayName = prop.Name;

            // Search in Metadata
            var metadata = type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().ToArray().FirstOrDefault();

            if (metadata != null)
            {
                var metaPropery = metadata.MetadataClassType.GetProperty(prop.Name);


                if (metaPropery != null)
                {
                    displayName = ((DisplayNameAttribute)metaPropery.GetCustomAttributes(typeof (DisplayNameAttribute), true).First()).DisplayName;
                }
            }


            results.Add(new ModelProperty
                            {
                                Name = prop.Name,
                                ValueExpression = "Model." + prop.Name,
                                UnderlyingType = underlyingType,
                                IsPrimaryKey = IsPrimaryKey(prop),
                                IsReadOnly = prop.GetSetMethod() == null,
                                DisplayName = displayName
                            });
        }
    }

    return results;
}

// Helper
private bool IsBindableType(Type type)
{
    return type.IsPrimitive || bindableNonPrimitiveTypes.Contains(type);
}
#>

Теперь вы можете получить доступ к этим атрибутам следующим образом:

<#
List<ModelProperty> properties = GetModelProperties(mvcHost.ViewDataType);
foreach (ModelProperty property in properties) {
    if (!property.IsPrimaryKey) {
#>
    <th>
        <#= property.DisplayName #><#= property.AllowEmptyStrings ? "*" : "" #>
    </th>
<#
    }
}
#>
0 голосов
/ 29 марта 2011

Это было бы возможно, но потребовало бы больше работы, чем у вас здесь.Вы можете добавить свойство Required в ModelProperty, а затем установить его путем поиска обязательного атрибута свойства при получении свойств модели.Вы можете взглянуть на код, который определяет, является ли свойство первичным ключом в шаблонах .tt для примера.

...