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

16

我在实现自定义模型绑定器进行验证方面找到了很多信息,但我并没有看到太多关于我要尝试做的事情。

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

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;
    }
}
有没有更简洁的方法来查看视图模型属性上的属性,或者我可以使用不同种类的属性吗?数据注释属性似乎真的是针对不同的问题。

更新

Craig的答案让我找到了正确的位置,但我想在这里放一些示例供其他人参考。

我最终得到的元数据提供程序如下:

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个回答

8

“正确”的方式(根据作者的说法)是编写模型元数据提供程序。链接中有一个示例。虽然不是特别“简单”,但它是有效的,而且你将会做MVC的其他内容。


我在跟随你的链接后觉得这有道理,但现在我不太确定了。 我实际上并不想改变任何数据注释属性的值,我只是想根据一个新属性更改模型本身的值(通过从我的上面的示例中添加“Bar”)。 调用metaData.Model +=“Bar”似乎对任何事情都没有真正的影响。 - Jared
在将自定义令牌添加到模型元数据后,您可以更改模型绑定程序以识别它们。 - Craig Stuntz
2
谢谢你的指针。我已经根据你分享的链接更新了主贴,并添加了一些示例。 - Jared

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