Welcome 微信登录

首页 / 网页编程 / ASP.NET / ASP.NET MVC是如何运行的(4): Action的执行

ASP.NET MVC是如何运行的(4): Action的执行2012-11-01 cnblogs Artech作为Controller基类ControllerBase的Execute方法的核心在于对Action方法的执行和作为方法返回的ActionResult的执行,两者的执行是通过一个叫做ActionInvoker的组件来完成的。

一、ActionInvoker

我们同样为ActionInvoker定义了一个接口IActionInvoker。如下面的代码片断所示,该接口定义了一个唯一的方法InvokeAction用于执行指定名称的Action方法,该方法的第一个参数是一个表示基于当前Controller上下文的ControllerContext对象。

 1: public interface IActionInvoker
2: {
3: void InvokeAction(ControllerContext controllerContext, string actionName);
4: }
ControllerContext类型在真正的ASP.NET MVC框架中要负责一些,在这里我们对它进行了简化,仅仅将它表示成对当前Controller和请求上下文的封装,而这两个要素分别通过如下所示的Controller和RequestContext属性表示。

 1: public class ControllerContext
2: {
3: public ControllerBase Controller { get; set; }
4: public RequestContext RequestContext { get; set; }
5: }
ControllerBase中表示ActionInvoker的同名属性在构造函数中被初始化。在Execute方法中,通过作为方法参数的RequestContext对象创建ControllerContext对象,并通过包含在RequestContext中的RouteData得到目标Action的名称,然后将这两者作为参数调用ActionInvoker的InvokeAction方法。

从前面给出的关于ControllerBase的定义我们可以看到在构造函数中默认创建的ActionInvoker是一个类型为ControllerActionInvoker的对象。如下所示的代码片断反映了整个ControllerActionInvoker的定义,而InvokeAction方法的目的在于实现针对Action方法的执行。由于Action方法具有相应的参数,在执行Action方法之前必须进行参数的绑定。ASP.NET MVC将这个机制成为Model的绑定,而这又涉及到另一个重要的组件ModelBinder。

 1: public class ControllerActionInvoker : IActionInvoker
2: {
3: public IModelBinder ModelBinder { get; private set; }
4: public ControllerActionInvoker()
5: {
6: this.ModelBinder = new DefaultModelBinder();
7: }
8: public void InvokeAction(ControllerContext controllerContext, string actionName)
9: {
10: MethodInfo method = controllerContext.Controller.GetType().GetMethods().First(m => string.Compare(actionName, m.Name, true) == 0);
11: List<object> parameters = new List<object>();
12: foreach (ParameterInfo parameter in method.GetParameters())
13: {
14: parameters.Add(this.ModelBinder.BindModel(controllerContext, parameter.Name, parameter.ParameterType));
15: }
16: ActionResult actionResult = method.Invoke(controllerContext.Controller, parameters.ToArray()) as ActionResult;
17: actionResult.ExecuteResult(controllerContext);
18: }
19: }
二、ModelBinder

我们为ModelBinder提供了一个如下一个简单的定义,这与在真正的ASP.NET MVC中的同名接口的定义不尽相同。该接口具有唯一的BindModel根据ControllerContext和Model名称(在这里实际上是参数名称)和类型得到一个作为参数的对象。

 1: public interface IModelBinder
2: {
3: object BindModel(ControllerContext controllerContext, string modelName, Type modelType);
4: }
通过前面给出的关于ControllerActionInvoker的定义我们可以看到在构造函数中默认创建的ModelBinder对象是一个DefaultModelBinder对象。由于仅仅是对ASP.NET MVC的模拟,定义在自定义的DefaultModelBinder中的Model绑定逻辑比ASP.NET MVC中同名类型中实现的要简单得多。