自定义模型绑定绑定嵌套的属性值 [英] Custom Model Binder to bind nested property values

查看:165
本文介绍了自定义模型绑定绑定嵌套的属性值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

究其原因,我需要这样的:在我的控制器之一,我要绑定在比我的应用程序的其余部分不同的方式,所有十进制值。我不想注册模型绑定在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆