发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
MVC通过路由系统,根据url找到对应的Action,然后再执行action,在执行action的时候,根据action的参数和数据来源比对,生成各个参数的值,这就是model binder.
MVC中这个核心处理逻辑都在ControllerActionInvoker里,用reflector看,能看能到这个类继承了IActionInvoker接口
1 public interface IActionInvoker 2 { 3 bool InvokeAction(ControllerContext controllerContext, string actionName); 4 }
所以咱们可以根据代码模拟写出自己的CustomActionInvoker
以下是我自己写的ActionInvoker类
1 public class CustomActionInvoker : IActionInvoker 2 { 3 4 public bool InvokeAction(ControllerContext controllerContext, string actionName) 5 { 6 bool flag = false; 7 try 8 { 9 //get controller type 10 Type controllerType = controllerContext.Controller.GetType(); 11 //get controller descriptor 12 ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerType); 13 //get action descriptor 14 ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName); 15 Dictionary<string, object> parameters = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); 16 //get parameter-value entity 17 foreach (ParameterDescriptor parameterDescriptor in actionDescriptor.GetParameters()) 18 { 19 Type parameterType = parameterDescriptor.ParameterType; 20 //get model binder 21 IModelBinder modelBinder = new CustomModelBinder(); 22 IValueProvider valueProvider = controllerContext.Controller.ValueProvider; 23 string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; 24 ModelBindingContext bindingContext = new ModelBindingContext(); 25 bindingContext.FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null; 26 bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType); 27 bindingContext.ModelName = str; 28 bindingContext.ModelState = controllerContext.Controller.ViewData.ModelState; 29 bindingContext.ValueProvider = valueProvider; 30 parameters.Add(parameterDescriptor.ParameterName, modelBinder.BindModel(controllerContext, bindingContext)); 31 } 32 ActionResult result = (ActionResult)actionDescriptor.Execute(controllerContext, parameters); 33 result.ExecuteResult(controllerContext); 34 flag = true; 35 } 36 catch (Exception ex) 37 { 38 //log 39 } 40 return flag; 41 } 42 }
以下详细解释下执行过程
执行过程中涉及到三个Descriptor,ControllerDescriptor,ActionDescriptor,ParameterDescriptor
ControllerDescriptor主要作用是根据action name获取到ActionDescriptor,代码中使用的是MVC自带的ReflectedControllerDescriptor,从名字就可以看出来,主要是靠反射获取到action.
ActionDescriptor,主要作用是获取parameterDescriptor,然后execute action.
parameterDescriptor,描述的是action的参数信息,包括name、type等
最核心的方法. 将传递的数据和参数一一对应,笔者是自己写的CustomModelBinder,MVC默认用的是DefaultModelBinder 都实现了接口IModelBinder
1 public interface IModelBinder 2 { 3 object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); 4 }
其中CustomModelBinder的代码如下
1 public class CustomModelBinder : IModelBinder 2 { 3 4 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 5 { 6 return this.GetModel(controllerContext, bindingContext.ModelType, bindingContext.ValueProvider, bindingContext.ModelName); 7 } 8 9 public object GetModel(ControllerContext controllerContext, Type modelType, IValueProvider valueProvider, string key) 10 { 11 if (!valueProvider.ContainsPrefix(key)) 12 { 13 return null; 14 } 15 return valueProvider.GetValue(key).ConvertTo(modelType); 16 } 17 }
注:我只是实现了简单的基本类型
中间有最核心的方法
valueProvider.GetValue(key).ConvertTo(modelType)
MVC默认提供了几种ValueProvider,每种都有对应的ValueProviderFactory,每种ValueProvider都对应着自己的数据源
1 ValueProviderFactoryCollection factorys = new ValueProviderFactoryCollection(); 2 factorys.Add(new ChildActionValueProviderFactory()); 3 factorys.Add(new FormValueProviderFactory()); 4 factorys.Add(new JsonValueProviderFactory()); 5 factorys.Add(new RouteDataValueProviderFactory()); 6 factorys.Add(new QueryStringValueProviderFactory()); 7 factorys.Add(new HttpFileCollectionValueProviderFactory());
上述过程讲完之后,还缺一个怎么应用上自己写的ActionInvoker,在Controller里提供了虚方法CreateActionInvoker
1 protected override IActionInvoker CreateActionInvoker() 2 { 3 return new CustomActionInvoker(); 4 }
到此,整个过程已讲完。
来自: 昵称10504424 > 《工作》
0条评论
发表
请遵守用户 评论公约
白话学习MVC(六)模型绑定
在这个自定义的ModelBinder中对复杂类型的绑定时,只能绑定上述User类那样的类型,但是在实际中还有存在嵌套类型的类,例如:public class User{ public int Id{set;get;} public string Name{set...
Asp.net MVC 示例项目Suteki.Shop分析之---ModelBinder
aaa
aaaModel.prototype.addCartButtonClick = function(event){var row = event.bindingContext.$object;if( rows.length == 0 ){this.comp("cartData").newData({defaultValues:[{"fMenuI...
ASP.NET MVC 流程概述(转)
if (View == null) { result = FindView(context);1)进入 result = FindView(context); 其实 调用的是ViewResult的Find...
NetCore3.0实现自定义IOC容器注入
foreach (var lib in libs) { if (!public class CloudControllerActivator : IControllerActivator { public object Create(ControllerContext context) { if (context == null) { throw new Argument...
我喜欢ASP.NET的MVC因为它牛逼的9大理由
我很早就关注ASP.NET的mvc的,因为最开始是学了Java的MVC,由于工作的原因一直在做.Net开发,最近的几个新项目我采用了MVC做了,我个一...
从零开始学习 ASP.NET MVC 1.0 (四) View/Model 全解
} return new ViewResult { View = view, ViewData = ViewData, TempData = TempData };ViewData的生命周期和View相同, 只对当前View有...
消失模铸造工艺分类及特点 classification and characteristics
Thelost foam casting can be divided into self-hardening sand (damp type with binder) lost foam casting anddry sand (dry type without binder ) lost foam casting according to its castmould...
[ASP.NET MVC 小牛之路]15
<form action="/Home/Names" method="post"> <div><label>1:</label><input id="...
微信扫码,在手机上查看选中内容