• 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 ();
    }
  • 相关阅读:
    if判断语句和循环语句
    列表,元祖,字典的详细概述
    day10
    day09
    day08
    java---基本程序设计总结
    day07
    day06
    day05
    day04
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/3639694.html
Copyright © 2020-2023  润新知