模型绑定时在视图模型属性上查找自定义属性

时间:2011-06-01 17:19:50

标签: asp.net-mvc custom-attributes model-binding

我发现了很多关于为验证目的实现自定义模型绑定器的信息,但我还没有看到我正在尝试做什么。

我希望能够根据视图模型中属性的属性来操作模型绑定器要设置的值。例如:

public class FooViewModel : ViewModel
{
    [AddBar]
    public string Name { get; set; }
}

AddBar只是

public class AddBarAttribute : System.Attribute
{
}

我无法在自定义模型绑定器的BindModel方法中找到一种在查看模型属性上查找属性的简洁方法。这有效,但感觉应该有一个更简单的解决方案:

public class FooBarModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = base.BindModel(controllerContext, bindingContext);

        var hasBarAttribute = false;

        if(bindingContext.ModelMetadata.ContainerType != null)
        {
            var property = bindingContext.ModelMetadata.ContainerType.GetProperties()
                .Where(x => x.Name == bindingContext.ModelMetadata.PropertyName).FirstOrDefault();
            hasBarAttribute = property != null && property.GetCustomAttributes(true).Where(x => x.GetType() == typeof(AddBarAttribute)).Count() > 0;
        }

        if(value.GetType() == typeof(String) && hasBarAttribute)
            value = ((string)value) + "Bar";

        return value;
    }
}

是否有更简洁的方法来查看视图模型属性上的属性或我可能使用的其他类型的属性? DataAnnotation属性似乎确实是针对不同的问题。

更新

克雷格的回答让我到了正确的地方,但我想我会在这里为其他人提供一些例子。

元数据提供程序我最终看起来像

public class FooBarModelMetadataProvider : 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);

        if(attributes.OfType<AddBarAttribute>().Any())
            metaData.AdditionalValues.Add("AddBarKey", true);

        return metaData;
    }
}

模型绑定器看起来像:

public class FooBarModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = base.BindModel(controllerContext, bindingContext);

        if(bindingContext.ModelMetadata.AdditionalValues.ContainsKey("AddBarKey"))
            value = ((string)value) + "Bar";

        return value;
    }
}

1 个答案:

答案 0 :(得分:8)

“正确”的方式(根据编写它的人)是write a model metadata provider。这个链接有一个例子。不完全是“简单”,但它确实有效,你将会做其他MVC所做的事情。