从HTML助手中提取显示名称和描述属性

8
我正在构建一个自定义的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);
  ...
}

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

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

[DisplayName("Titel")]

问题是我也需要一个描述。有一个称为Display的属性,它具有名称和描述,但我不知道如何使用上述代码中的元数据变量提取它?

1个回答

20

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

假设有以下模型:

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

以下是视图:

<%= Html.LabelFor(x => x.SomeProperty, true) %>

你可以在自定义辅助函数中从元数据获取这些信息:

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
    ...
}

备注:在模型属性上同时使用[DisplayName("foo")][Display(Name = "bar")]是冗余的,并且在metadata.DisplayName中使用的名称将优先于[Display]属性中使用的名称。


更新:

我的先前答案在ASP.NET MVC 2.0中无法使用。在.NET 3.5中,默认情况下无法使用DataAnnotations填充一些属性,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;
    }
}

您需要在Application_Start中注册它:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ModelMetadataProviders.Current = new DisplayMetaDataProvider();
}

然后助手应该按预期工作:

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
    ...
}

谢谢!但是这个不起作用,DisplayName和Description是null吗?请注意,这是在MVC2中而不是MVC3中。如果我理解正确的话,你的解决方案只适用于MVC3? - Banshee
@SnowJim,是的,在.NET 3.5中有一些属性无法使用DataAnnotations默认填充,其中Description就是其中之一。在.NET 4.0中应该可以工作。 - Darin Dimitrov
1
@SnowJim,请查看我的更新,其中包含ASP.NET MVC 2的解决方法。 - Darin Dimitrov
这是我遇到过的最全面的答案之一,所以+1。谢谢@DarinDimitrov! - RvdV79

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接