MVC中Action参数绑定的过程

一、题外话

上一篇:MVC中Action的执行过程

ControllerContext

封装有了与指定的 RouteBaseControllerBase 实例匹配的 HTTP 请求的信息。

二、Model绑定者

2.1相关说明

http请求中的参数绑定到Model,是由实现了IModelBinder的类来完成的。我们称这样的类叫做Model绑定者

using System;
namespace System.Web.Mvc
{
    /// <summary>Defines the methods that are required for a model binder.</summary>
    public interface IModelBinder
    {
        /// <summary>Binds the model to a value by using the specified controller context and binding context.</summary>
        /// <returns>The bound value.</returns>
        /// <param name="controllerContext">The controller context.</param>
        /// <param name="bindingContext">The binding context.</param>
        object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
    }
}

2.2Model绑定者实现绑定的途径

1)直接在参数上绑定

using System;
using System.Web;
using System.Web.Mvc;

namespace MVC_ST_2.Controllers
{

    public class Person
    {

        public string Name { get; set; }

        public int Age { get; set; }

    }

    public class PersonModelBinder : IModelBinder
    {

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;
            var p = new Person();
            p.Name = request["Name"];
            p.Age =int.Parse( request["Age"]);
            return p;
        }

    }

    public class HomeController : Controller
    {
        //通过参数标记
        public ActionResult Index([ModelBinder(typeof(PersonModelBinder))] Person p)
        {
            return View();
        }

        public ActionResult Index2(Person p)
        {
            return View();
        }
    }
}

2)在model上加标记

    [ModelBinder(typeof(PersonModelBinder))]
    public class Person
    {

        public string Name { get; set; }

        public int Age { get; set; }

    }

3)ModelBinders.Binders中注册

protected void Application_Start()

{
    ModelBinders.Binders[typeof(Person)] = new PersonModelBinder();
}

 

2.3 Action中是如何调用绑定者的?

以下是

private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor)
{
    return parameterDescriptor.BindingInfo.Binder ?? this.Binders.GetBinder(parameterDescriptor.ParameterType);
}

说明:通过参数标记的方式优先,如果没有则使用this.Binders.GetBinder(parameterDescriptor.ParameterType);

this.Binders的定义

protected internal ModelBinderDictionary Binders
{
    get
    {
        if (this._binders == null)
        {
            this._binders = ModelBinders.Binders;
        }
        return this._binders;
    }
    set
    {
        this._binders = value;
    }
}

从上图可以看出,最终的绑定操作交给了ModelBinderDictionary(注意了,下面会接着讲)

正好我们回到前两章讲的ControllerActionInvoker,其中的参数绑定赋值过程GetParameterValues,如何获取的过程即绑定的过程

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
    Type parameterType = parameterDescriptor.ParameterType;
    IModelBinder modelBinder = this.GetModelBinder(parameterDescriptor);
    IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
    string modelName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
    Predicate<string> propertyFilter = ControllerActionInvoker.GetPropertyFilter(parameterDescriptor);
    ModelBindingContext bindingContext = new ModelBindingContext
    {
        FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null,
        ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),
        ModelName = modelName,
        ModelState = controllerContext.Controller.ViewData.ModelState,
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
    };
    object obj = modelBinder.BindModel(controllerContext, bindingContext);
    return obj ?? parameterDescriptor.DefaultValue;
}
private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor)
{
    return parameterDescriptor.BindingInfo.Binder ?? this.Binders.GetBinder(parameterDescriptor.ParameterType);
}
 this.Binders 其类型正好是ModelBinderDictionary(上面提到过),他的方法如下
    public IModelBinder GetBinder(Type modelType)
        {
            return this.GetBinder(modelType, true);
        }
        /// <summary>Retrieves the model binder for the specified type or retrieves the default model binder.</summary>
        /// <returns>The model binder.</returns>
        /// <param name="modelType">The type of the model to retrieve.</param>
        /// <param name="fallbackToDefault">true to retrieve the default model binder.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="modelType" /> parameter is null.</exception>
        public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }
            return this.GetBinder(modelType, fallbackToDefault ? this.DefaultBinder : null);       //this.DefaultBinder 是下一章我们需要讲的内容。也是整个MVC核心的默认的绑定者
        }
        private IModelBinder GetBinder(Type modelType, IModelBinder fallbackBinder)
        {
            IModelBinder modelBinder = this._modelBinderProviders.GetBinder(modelType);
            if (modelBinder != null)
            {
                return modelBinder;
            }
            if (this._innerDictionary.TryGetValue(modelType, out modelBinder))
            {
                return modelBinder;
            }
            modelBinder = ModelBinders.GetBinderFromAttributes(modelType, () => string.Format(CultureInfo.CurrentCulture, MvcResources.ModelBinderDictionary_MultipleAttributes, new object[]
            {
                modelType.FullName
            }));
            return modelBinder ?? fallbackBinder;//DefaultBinder 很多情况下,前面的几个if都不会执行,所以使用系统默认的绑定者
        }

三、下一章接着介绍DefaultModelBinder

MVC中Action参数绑定的过程

时间: 2024-08-11 10:26:20

MVC中Action参数绑定的过程的相关文章

MVC中Action的执行过程

接着上一篇:MVC控制器的激活过程 一.代码现行,该伪代码大致解析了Action的执行的过程 try { Run each IAuthorizationFilter's OnAuthorization() method if(none of the IAuthorizationFilters cancelled execution) { Run each IActionFilter's OnActionExecuting() method Run the action method Run ea

mvc action 参数绑定——值提供器【学习笔记】

每次http请求的各种数据(表单数据.url的数据.路由数据等等)都保存在不同的IValueProvider接口的实现类中. 而IValueProvider接口的实现类是通过ValueProviderFactory创建的. 在mvc中原生的ValueProviderFactory有六种: ChildActionValueProviderFactory:根据给定的Controller上下文创建一个ChildActionValueProvider对象. FormValueProviderFactor

NHibernate中Session与ASP.NET MVC中Action的综合使用

NHibernate的基本特征是完成面向对象的程序设计语言到关系数据库的映射,在NHibernate中使用持久化对象PO(Persistent Object)完成持久化操作,对PO的操作必须在Session管理下才能同步到数据库, 但是这里的Session并非指HttpSession,可以理解为基于ADO.NET的Connnection,Session是NHibernate运作的中心,对象的生命周期.事务的管理.数据库的存取都与Session息息相关,首先,我们需要知道, SessionFact

【SpringMVC学习05】SpringMVC中的参数绑定总结

众所周知,springmvc是用来处理页面的一些请求,然后将数据再通过视图返回给用户的,前面的几篇博文中使用的都是静态数据,为了能快速入门springmvc,在这一篇博文中,我将总结一下springmvc中如何接收前台页面的参数,即springmvc中的参数绑定问题. 1. 参数绑定的过程 我们可以回忆一下,在struts2中,是通过在Action中定义一个成员变量来接收前台传进来的参数,而在springmvc中,接收页面提交的数据是通过方法形参来接收的.从客户端请求的key/value数据,经

【SpringMVC学习05】SpringMVC中的参数绑定总结——较乱后期准备加入 同一篇幅他人的参数绑定

众所周知,springmvc是用来处理页面的一些请求,然后将数据再通过视图返回给用户的,前面的几篇博文中使用的都是静态数据,为了能快速入门springmvc,在这一篇博文中,我将总结一下springmvc中如何接收前台页面的参数,即springmvc中的参数绑定问题. 本篇建议不敲代码 只是看看 因为无法很好衔接 上一篇: 1. 参数绑定的过程 我们可以回忆一下,在struts2中,是通过在Action中定义一个成员变量来接收前台传进来的参数,而在springmvc中,接收页面提交的数据是通过方

SpringMVC中的参数绑定总结

众所周知,springmvc是用来处理页面的一些请求,然后将数据再通过视图返回给用户的,前面的几篇博文中使用的都是静态数据,为了能快速入门springmvc,在这一篇博文中,我将总结一下springmvc中如何接收前台页面的参数,即springmvc中的参数绑定问题. 1. 参数绑定的过程 我们可以回忆一下,在struts2中,是通过在Action中定义一个成员变量来接收前台传进来的参数,而在springmvc中,接收页面提交的数据是通过方法形参来接收的.从客户端请求的key/value数据,经

SpringMVC中的参数绑定

SpringMVC中的参数绑定 参数绑定的定义 所谓参数绑定,简单来说就是客户端发送请求,而请求中包含一些数据,那么这些数据怎么到达 Controller.从客户端请求key/value数据(比如get请求中包含的数据),经过参数绑定,将key/value数据绑定到controller方法的形参上.springmvc中,接收页面提交的数据是通过方法形参来接收.而不是在controller类定义成员变量接收. SpringMVC中默认支持的类型 自定义参数类型进行绑定 对于有些参数类型,由于我们输

ThinkPHP3.1新特性:Action参数绑定

Action参数绑定功能提供了URL变量和操作方法的参数绑定支持,这一功能可以使得你的操作方法定义和参数获取更加清晰,也便于跨模块调用操作方法了.这一新特性对以往的操作方法使用没有任何影响,你也可以用新的方式来改造以往的操作方法定义.Action参数绑定的原理是把URL中的参数(不包括分组.模块和操作地址)和控制器的操作方法中的参数进行绑定.例如,我们给Blog模块定义了两个操作方法read和archive方法,由于read操作需要指定一个id参数,archive方法需要指定年份(year)和月

Hibernate-ORM:07.Hibernate中的参数绑定

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客会讲解Hibernate中的参数绑定,就是相当于sql语句中的where后面的条件 一,讲解概述: 1.通过下标的方式绑定参数 2.通过自定义参数名的方式绑定参数(多用于多表操作) 3.通过传入自定义对象的方式绑定参数(多用于单表操作) 4.通过类似智能标签的方式绑定参数(多用于带条件的多表操作) 二,通过下标的方式绑定参数 @Test /*通过下标的方式指定参数*/ public void t01