zoukankan      html  css  js  c++  java
  • Asp.net MVC的Model Binder工作流程以及扩展方法(3)

    Default Binder是MVC中的清道夫,把守着Model Binder中的最后一道防线。如果我们没有使用Custom Model Binder等特殊处理,那么Model的绑定都是有Default Binder处理的。这篇文章,一起看看Default Binder和如何扩展Default Binder.

    一,Default Binder的流程

    下面的图是Default Model Binder中的关键方法BindModel的代码逻辑图。

    ValueProvider是包装好的类似于字典容器,里面包含了所有request中能够获取到的值(无论是Form提交的,还是Querystring中的)

    1. 假如我们绑定一个简单的int参数,那么Default Binder会在ValueProvder中直接找到对应值,然后返回。
    2. 如果绑定的是复杂类型(图中的Complex Model),比如对象,则会遍历每个属性,然后绑定该属性的值。如果属性是简单类型,就走上面的1流程;如果不是,就继续进行2流程。

    可以看出,Default Model Binder是一个比较复杂和巧妙的过程。在扩展Default Binder的时候,如果override BindeModel方法,不会全盘重写,而是一个”修饰“的过程。
    另外,在BindeModel过程中,有对于数据的验证的,这是和我们之前介绍的Custom Model Binder和Binder Attribute不同的地方

    mvc_default_model_binding_flow

    二,覆盖方法,改变Default Binder行为

    这里应用stackoverflow上的一个例子。原文地址: http://stackoverflow.com/questions/8729139/manipulate-model-value-before-passing-it-to-defaultmodelbinder-bindmodel

    问题:
    input中要求用户输入百分比值,但是不过分限定用户输入值的格式,比如用户可以输入50, 50%, 后台代码希望提交绑定后的值是个decimal类型,也就是说,在用户输入50, 50%的情况下,后台代码得到的是0.5

    首先看看,属性是如何定义的。下面代码中的FooPercent 就是我们用来保存百分比的属性。

    [DataType("Percent")]
    [Display(Name = "Percent of foo completed")]
    [Range(0.0d, 1.0d, ErrorMessage="The field {0} must be between {1:P0} and {2:P0}.")]
    public decimal? FooPercent { get; set; }

    接下来,创建PercentModelBinder继承自DefaultModelBinder. 发现DataType是Percent的绑定对象,会先尝试绑定。

    public class PercentModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext,
                                         ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelMetadata.DataTypeName == "Percent")
            {
                ValueProviderResult result =
                    bindingContext.ValueProvider.GetValue(
                        bindingContext.ModelName);
                if (result != null)
                {
                    string stringValue =
                        (string)result.ConvertTo(typeof(string));
                    decimal decimalValue;
                    if (!string.IsNullOrWhiteSpace(stringValue) &&
                        decimal.TryParse(
                            stringValue.TrimEnd(new char[] { '%', ' ' }),
                            out decimalValue))
                    {
                        return decimalValue / 100.0m;
                    }
                }
            }
            return base.BindModel(controllerContext, bindingContext);
        }
    }

    最后,替换MVC原有的DefaultModelBinder

    protected void Application_Start() 
    {
        ModelBinders.Binders.DefaultBinder = new PercentModelBinder ();
    }
  • 相关阅读:
    左偏树
    论在Windows下远程连接Ubuntu
    ZOJ 3711 Give Me Your Hand
    SGU 495. Kids and Prizes
    POJ 2151 Check the difficulty of problems
    CodeForces 148D. Bag of mice
    HDU 3631 Shortest Path
    HDU 1869 六度分离
    HDU 2544 最短路
    HDU 3584 Cube
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/3639694.html
Copyright © 2011-2022 走看看