上次讲到请求如何激活Controller和Action,这次讲下MVC中路由的使用。
本次两个关注点:
- 遗留:ModelBinder.BindModel的过程
- MVC中路由的使用
- MVC 5中的Action新特性
一、ModelBinder.BindModel的过程
MVCHander –> ProcessRequest()
xxxxxController\ControllerFactory
IController.Excute();
ControllerBase.Excute().ExcuteCore()
Controller.ExecuteCore() { . GetActionName ; IActionInvoker.InvokeAction() }
IActionInvoker.InvokeAction() {
get methodInfo //sys
处理参数 // BindModel
methodInfo.invoke();//sys
}
在MVC源码中,ControllerActionInvoker.InvokeAction()
我们看看BindModel做了些什么。
1:
class DefaultModelBinder : IModelBinder
3: {
/// <summary>
/// ControllerContext (控制器上下文,包含Controller 类型实例,和 当前请求上下文RequestContext)
/// MVC Model Bind, 从 ControllerContext 中,为当前参数(确定的类型 和 名称)赋值。
/// </summary>
/// <returns></returns>
string modelName, Type modelType)
13: {
// 值类型 或 对象值类型(string),即简单点说:值类型
string) == modelType)
16: {
object instance;
//获取值类型的 值实例,并返回
out instance))
20: {
return instance;
22: };
return Activator.CreateInstance(modelType);
24: }
25:
//不是值类型,即 对象类型
//使用类型默认构造函数,创建一个实例
object modelInstance = Activator.CreateInstance(modelType);
//下边就是一个循环的过程,查找对象的属性,值类型的就赋值,循环属性直至完成
in modelType.GetProperties())
31: {
//忽略了 action参数 的对象类型中“对象类型”的属性
string)))
34: {
continue;
36: }
object propertyValue;
out propertyValue))
39: {
null);
41: }
42: }
return modelInstance;
44: }
45:
/// <summary>
/// 为值类型 或 对象值类型(string),(即简单点说:值类型)获取值。
/// 结构体(数值,bool,自定义结构体struct),枚举enum,可空类型
/// </summary>
/// <returns></returns>
value)
56: {
//HttpPost 提交,使用窗体变量集合
58: var form = HttpContext.Current.Request.Form;
string key;
//form集合不为空
null != form)
62: {
//窗体变量集合 AllKeys 里查找 “modelName” 变量。
true) == 0);
null)
66: {
//?结构体
//value = Convert.ChangeType(form[key]., modelType);
69: var curKeyVal = form[key];
value = Convert.ChangeType(curKeyVal, modelType);
true;
72: }
73: }
//HttpGet 提交,使用路由值中的 QueryString
75: key = controllerContext.RequestContext.RouteData.Values
//更快!
//.Where(item => string.Equals(item.Key, modelName,StringComparison.InvariantCultureIgnoreCase))
true) == 0)
//get提交中,只取当前key的第一个匹配项的值
80: .Select(item => item.Key).FirstOrDefault();
null != key)
82: {
value = Convert.ChangeType(controllerContext.RequestContext.RouteData.Values[key], modelType);
true;
85: }
86:
//http://msdn.microsoft.com/zh-cn/library/system.web.routing.routedata.datatokens.aspx
//RouteData.DataTokens 属性
//与RouteData.Values类似的键值对方式,允许按key获取值。
//没试出与 RouteData.Values的区别???
91: key = controllerContext.RequestContext.RouteData.DataTokens
true) == 0)
93: .Select(item => item.Key).FirstOrDefault();
null != key)
95: {
value = Convert.ChangeType(controllerContext.RequestContext.RouteData.DataTokens[key], modelType);
true;
98: }
null;
false;
101: }
102: }