自定义模型绑定绑定嵌套的属性值 [英] Custom Model Binder to bind nested property values
问题描述
究其原因,我需要这样的:在我的控制器之一,我要绑定在比我的应用程序的其余部分不同的方式,所有十进制值。我不想注册模型绑定在Global.asax中(通过 ModelBinders.Binders.Add(typeof运算(十进制),新DecimalModelBinder());
)
The reason I need this: In one of my controllers I want to bind all Decimal values in a different way than the rest of my application. I do not want to register a Model Binder in Global.asax (via ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
)
我试图从 DefaultModelBinder
类派生并覆盖其 BindProperty
方法,但仅适用于模型实例的直接(不嵌套)十进制属性。
I have tried deriving from the DefaultModelBinder
class and override its BindProperty
method, but that only works for the model instance's immediate (not nested) Decimal properties.
我有以下的例子来说明我的问题:
I have the following example to demonstrate my problem:
namespace ModelBinderTest.Controllers
{
public class Model
{
public decimal Decimal { get; set; }
public DecimalContainer DecimalContainer { get; set; }
}
public class DecimalContainer
{
public decimal DecimalNested { get; set; }
}
public class DecimalModelBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.PropertyType == typeof (decimal))
{
propertyDescriptor.SetValue(bindingContext.Model, 999M);
return;
}
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
public class TestController : Controller
{
public ActionResult Index()
{
Model model = new Model();
return View(model);
}
[HttpPost]
public ActionResult Index([ModelBinder(typeof(DecimalModelBinder))] Model model)
{
return View(model);
}
}
}
此解决方案仅设置了模式
的小数
属性为999,但不会做任何 DecimalContainer
的 DecimalNested
属性。我知道这是因为 base.BindProperty
被称为我的 DecimalModelBinder
BindProperty
覆盖,但我不知道如何说服基类带小数点的属性打交道时,用我的模型绑定。
This solution only sets the Model
's Decimal
property to 999, but doesn't do anything to DecimalContainer
's DecimalNested
property. I realize this is because base.BindProperty
is called in my DecimalModelBinder
's BindProperty
override, but I don't know how to convince the base class to use my Model Binder when dealing with decimal properties.
推荐答案
您可以无条件申请模型绑定在你的的Application_Start
:
You could apply the model binder unconditionally in your Application_Start
:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
再有一个自定义的授权过滤器(是的,因为模型绑定之前运行的授权过滤器),将注入的HttpContext一定的价值,可能后来被模型绑定使用:
and then have a custom authorization filter (yes, authorization filter as it runs before the model binder) that will inject into the HttpContext some value that could later be used by the model binder:
[AttributeUsage(AttributeTargets.Method)]
public class MyDecimalBinderAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.HttpContext.Items["_apply_decimal_binder_"] = true;
}
}
,然后如果HttpContext的包含自定义值befoire应用它的模型绑定测试:
and then in your model binder test if the HttpContext contains the custom value befoire applying it:
public class DecimalModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext.HttpContext.Items.Contains("_apply_decimal_binder_"))
{
// The controller action was decorated with the [MyDecimalBinder]
// so we can proceed
return 999M;
}
// fallback to the default binder
return base.BindModel(controllerContext, bindingContext);
}
}
现在所有剩下的就是用自定义过滤器,以使小数粘结剂来装饰你的控制器动作:
Now all that's left is to decorate your controller action with the custom filter to enable the decimal binder:
[HttpPost]
[MyDecimalBinder]
public ActionResult Index(Model model)
{
return View(model);
}
这篇关于自定义模型绑定绑定嵌套的属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!