寻找定制的视图模型属性的属性时,模型绑定 [英] Finding custom attributes on view model properties when model binding
问题描述
我发现了很多的信息,实施验证目的的自定义模型绑定,但我还没有看到太多关于什么,我试图做的。
我希望能够操纵该模型粘合剂将基于在视图模型中的财产属性设置的值。例如:
公共类FooViewModel:视图模型
{
[AddBar]
公共字符串名称{;组; }
}
AddBar只是
公共类AddBarAttribute:System.Attribute
{
}
我没能找到一个干净的方法来找到在自定义模型绑定的BindModel方法的视图模型属性的属性。这工作,但感觉应该有一个简单的解决方案:
公共类FooBarModelBinder:DefaultModelBinder
{
公众覆盖对象BindModel(ControllerContext controllerContext,ModelBindingContext的BindingContext)
{
VAR值= base.BindModel(controllerContext,BindingContext中); VAR hasBarAttribute = FALSE; 如果(bindingContext.ModelMetadata.ContainerType!= NULL)
{
VAR财产= bindingContext.ModelMetadata.ContainerType.GetProperties()
。凡(X => x.Name == bindingContext.ModelMetadata.PropertyName).FirstOrDefault();
hasBarAttribute =属性= NULL&放大器;!&安培; property.GetCustomAttributes(真)。凡(X => x.GetType()== typeof运算(AddBarAttribute))计数()> 0;
} 如果(value.GetType()== typeof运算(字符串)及和放大器; hasBarAttribute)
值=((字符串)值)+酒吧; 返回值;
}
}
有没有查看视图模型属性或不同类型的属性,我可以使用属性的更清洁的方式?该DataAnnotation属性似乎真的是一个不同的问题。
更新
克雷格的回答让我在正确的地方,但我想我会放一些例子,在这里为别人着想。
中的元数据提供商我结束了看起来像
公共类FooBarModelMetadataProvider:DataAnnotationsModelMetadataProvider
{
保护覆盖ModelMetadata CreateMetadata(IEnumerable的<属性与GT;属性,类型containerType,Func键<对象> modelAccessor,类型modelType,弦乐propertyName的)
{
VAR元= base.CreateMetadata(属性,containerType,modelAccessor,modelType,propertyName的); 如果(attributes.OfType< AddBarAttribute>()任何()。)
metaData.AdditionalValues.Add(AddBarKey,真正的); 返回元数据;
}
}
模型绑定如下:
公共类FooBarModelBinder:DefaultModelBinder
{
公众覆盖对象BindModel(ControllerContext controllerContext,ModelBindingContext的BindingContext)
{
VAR值= base.BindModel(controllerContext,BindingContext中); 如果(bindingContext.ModelMetadata.AdditionalValues.ContainsKey(AddBarKey))
值=((字符串)值)+酒吧; 返回值;
}
}
正确的方式(每谁写的家伙)是<一个href=\"http://bradwilson.typepad.com/blog/2010/01/why-you-dont-need-modelmetadataattributes.html\">write模型元数据提供商。有在链路的例子。没有precisely简单,但它的作品,你会做什么MVC的其余部分一样。
I've found a lot of information on implementing a custom model binder for validation purposes but I haven't seen much about what I'm attempting to do.
I want to be able to manipulate the values that the model binder is going to set based on attributes on the property in the view model. For instance:
public class FooViewModel : ViewModel
{
[AddBar]
public string Name { get; set; }
}
AddBar is just
public class AddBarAttribute : System.Attribute
{
}
I've not been able to find a clean way to find the attributes on a view model property in the custom model binder's BindModel method. This works but it feels like there should be a simpler solution:
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;
}
}
Is there a cleaner way to view the attributes on the view model property or a different kind of attribute I could be using? The DataAnnotation attributes really seem to be for a different problem.
UPDATE
Craig's answer got me to the right place but I thought I'd put some examples in here for others.
The metadata provider I ended up with looks like
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;
}
}
The model binder looks like:
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;
}
}
The "correct" way (per the guy who wrote it) is to write a model metadata provider. There's an example at the link. Not precisely "simple," but it works, and you'll be doing what the rest of MVC does.
这篇关于寻找定制的视图模型属性的属性时,模型绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!