如何注入自定义ModelMetadata属性并在Html帮助器中使用它们

时间:2011-02-10 08:52:04

标签: asp.net-mvc asp.net-mvc-3 metadata

想法(简化)是在字典中包含的ViewModel中具有用户可定义的属性。这些方面的东西:

public class MyViewModel
{
    [Required]
    public string Name { get; set; }

    [DisplayName("User address")]
    public string Address { get; set; }

    // ...

    public IDictionary<string, string> MetaData { get; set; }
}

假设MetaData包含几个额外的属性PhoneNumberEmail等,您可以使用myViewModel.MetaData["PhoneNumber"]进行访问。

我想要做的是能够在View端的Html助手中使用那些额外的MetaData 属性,就像我使用普通属性一样。

因此,除了使用标准属性:

Html.TextBox("Name")

我还想使用这些附加属性:

Html.TextBox("PhoneNumber")

我的研究让我继承自DataAnnotationsModelMetadataProvider(因为它还需要支持标准属性的标准DataAnnotations属性)并试图找出究竟要覆盖的内容以便注入附加属性作为额外的ModelMetadata元素,但我有点卡住了。

我是在正确的道路上吗?任何可以帮助我的额外指针?

由于

1 个答案:

答案 0 :(得分:2)

另一种选择可能是构建一个类似于MVC 3中的ViewBag / ViewData的动态对象。你可以通过Model.MetaData.Foo访问一个对象,而Foo实际上会映射到一个键你的字典。

支持ViewBag对象的类型是System.Web.Mvc.DynamicViewDataDictionary;这个类是内部和密封的,所以你必须自己实现它(除非有一个我不知道的更好的选项)。快速浏览一下MVC 3源代码就可以了:

internal sealed class DynamicViewDataDictionary : DynamicObject {
    private readonly Func<ViewDataDictionary> _viewDataThunk;

    public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk) {
        _viewDataThunk = viewDataThunk;
    }

    private ViewDataDictionary ViewData {
        get {
            ViewDataDictionary viewData = _viewDataThunk();
            Debug.Assert(viewData != null);
            return viewData;
        }
    }

    // Implementing this function improves the debugging experience as it provides the debugger with the list of all
    // the properties currently defined on the object
    public override IEnumerable<string> GetDynamicMemberNames() {
        return ViewData.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        result = ViewData[binder.Name];
        // since ViewDataDictionary always returns a result even if the key does not exist, always return true
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value) {
        ViewData[binder.Name] = value;
        // you can always set a key in the dictionary so return true
        return true;
    }
}

此解决方案相对于修改ModelMetadataProvider的一个可能的优势是,您不必花时间为您的方案构建所有自定义组件 - 默认提供程序就足够了。