从HTML帮助程序中提取显示名称和描述属性

Ban*_*hee 8 c# reflection attributes html-helper asp.net-mvc-2

我正在构建一个如下所示的自定义HTML.LabelFor助手:

public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression, Boolean showToolTip)
{
  var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
  ...
}
Run Code Online (Sandbox Code Playgroud)

为了能够获得属性的正确名称,我使用以下代码:

metadata.DisplayName
Run Code Online (Sandbox Code Playgroud)

在ModelView类的属性上我得到了:

[DisplayName("Titel")]
Run Code Online (Sandbox Code Playgroud)

问题是我还需要一个描述.有一个名为Display的属性,它有名称和描述,但我没有看到如何使用上面代码中的元数据变量来提取它?

Dar*_*rov 20

免责声明:以下内容仅适用于ASP.NET MVC 3(如果您使用的是以前的版本,请参阅底部的更新)

假设以下型号:

public class MyViewModel
{
    [Display(Description = "some description", Name = "some name")]
    public string SomeProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

以下观点:

<%= Html.LabelFor(x => x.SomeProperty, true) %>
Run Code Online (Sandbox Code Playgroud)

在您的自定义帮助程序中,您可以从元数据中获取此信息:

public static MvcHtmlString LabelFor<TModel, TValue>(
    this HtmlHelper<TModel> self, 
    Expression<Func<TModel, TValue>> expression, 
    bool showToolTip
)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
    var description = metadata.Description; // will equal "some description"
    var name = metadata.DisplayName; // will equal "some name"
    // TODO: do something with the name and the description
    ...
}
Run Code Online (Sandbox Code Playgroud)

备注:拥有[DisplayName("foo")][Display(Name = "bar")]使用相同的模型属性是多余的,并且[Display]属性中使用的名称具有优先权metadata.DisplayName.


更新:

我之前的回答不适用于ASP.NET MVC 2.0.有一些属性,默认情况下不能DataAnnotations在.NET 3.5中填充,并且Description是其中之一.要在ASP.NET MVC 2.0中实现此目的,您可以使用自定义模型元数据提供程序:

public class DisplayMetaDataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType,
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName
    )
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        var displayAttribute = attributes.OfType<DisplayAttribute>().FirstOrDefault();
        if (displayAttribute != null)
        {
            metadata.Description = displayAttribute.Description;
            metadata.DisplayName = displayAttribute.Name;
        }
        return metadata;
    }
}
Run Code Online (Sandbox Code Playgroud)

你要注册的Application_Start:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ModelMetadataProviders.Current = new DisplayMetaDataProvider();
}
Run Code Online (Sandbox Code Playgroud)

然后帮助器应该按预期工作:

public static MvcHtmlString LabelFor<TModel, TValue>(
    this HtmlHelper<TModel> self, 
    Expression<Func<TModel, TValue>> expression, 
    bool showToolTip
)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
    var description = metadata.Description; // will equal "some description"
    var name = metadata.DisplayName; // will equal "some name"
    // TODO: do something with the name and the description
    ...
}
Run Code Online (Sandbox Code Playgroud)