技术开发 频道

ASP.NET Web应用真实模拟MVC的路由机制

  五、通过MvcHandler处理请求

  在UrlRoutingModule映射的实际上是具有如下定义的MvcHandler,它具有一个RequestContext属性通过构造函数进行初始化。在ASP.NET MVC中,真正的请求处理体现在根据路由信息创建Controller,并执行相应的Action方法。这两个步骤体现的ProcessRequest方法中。

1: public class MvcHandler: IHttpHandler
2: {
3: public RequestContext RequestContext{get; private set;}
4: public IControllerFactory ControllerFactory
5: {
6: get { return ControllerBuilder.Current.GetControllerFactory(); }
7: }
8: public MvcHandler(RequestContext requestContext)
9: {
10: this.RequestContext = requestContext;
11: }
12: public bool IsReusable
13: {
14: get { return false; }
15: }
16: public void ProcessRequest(HttpContext context)
17: {
18: RouteData routeData = this.RequestContext.RouteData;
19: var controller = this.ControllerFactory.CreateController(this.RequestContext, routeData.Controller);
20: controller.Execute(this.RequestContext);
21: }
22: }

  Controller实现了具有如下定义的接口IController,所有Action方法都通过Execute方法执行,该方法的参数的表示当前请求上下文的RequestContext对象。IController通过相应的Controller工厂创建,下面的代码同时也定义了Controller工厂接口的定义。

1: public interface IController
2: {
3: void Execute(RequestContext requestContext);
4: }
5: public interface IControllerFactory
6: {
7: IController CreateController(RequestContext requestContext, string controllerName);
8: }

  我们定义了如下一个简单名称为DefaultController,它的Execute方法定义很简单:通过包含在RequestContext的RouteData得到当前的Action,并将它作为方法名得到相应的MethodInfo对象,滨个通过反射调用它得到一个ActionResult对象,最后执行ActionResult的ExecuteResult方法。该方法的参数是基于RequestContext创建的另一个上下文ControllerContext。

1: public class DefaultController : IController
2: {
3: public void Execute(RequestContext requestContext)
4: {
5: string action = requestContext.RouteData.Action;
6: MethodInfo method = this.GetType().GetMethod(action);
7: ActionResult result = (ActionResult)method.Invoke(this, null);
8: ControllerContext controllerContext = new ControllerContext
9: {
10: RequestContext = requestContext
11: };
12: result.ExecuteResult(controllerContext);
13: }
14: }

  我们定义了具有如下定义的Controller工厂类DefaultControllerFactory。创建Controller的逻辑也不复杂:通过RouteData表示的Controller名称得到相应的Controller类型,通过反射创建Controller对象。由于RouteData中只包含Controller的名称,所以需要通过命名空间和程序集的辅助才能解析出真正的类型。

1: class DefaultControllerFactory : IControllerFactory
2: {
3: public IController CreateController(RequestContext requestContext, string controllerName)
4: {
5: RouteData routeData = requestContext.RouteData;
6: string controllerType = string.Format("{0}Controller", controllerName);
7: IController controller;
8: controller = this.CreateControler(controllerType);
9: if (null != controller)
10: {
11: return controller;
12: }
13: foreach (string assembly in routeData.Assemblies)
14: {
15: controller = this.CreateControler(controllerType, assembly);
16: if (null != controller)
17: {
18: return controller;
19: }
20:
21: foreach (string ns in routeData.Namespaces)
22: {
23: controllerType = string.Format("{0}.{1}Controller", ns, controllerName);
24: controller = this.CreateControler(controllerType, assembly);
25: if (null != controller)
26: {
27: return controller;
28: }
29: }
30: }
31:
32: throw new InvalidOperationException("Cannot locate the controller");
33: }
34: private IController CreateControler(string controllerType, string assembly = null)
35: {
36: Type type = null;
37: if (null == assembly)
38: {
39: type = Type.GetType(controllerType);
40: }
41: else
42: {
43: type = Assembly.Load(assembly).GetType(controllerType);
44: }
45: if (null == type)
46: {
47: return null;
48: }
49: return Activator.CreateInstance(type) as IController;
50: }
51: }

  六、将ActionResult写入Http回复

  Controller的Action方法的返回值为具有如下定义的ActionResult类型,通过ExecuteResult方法将相应的执行结果写入HTTP回复中。我定义了如下一个StaticViewResult,它根据RouteData中的Action信息找到匹配的.html静态文件,并将文件的内容写入HttpResponse。

1: public abstract class ActionResult
2: {
3: public abstract void ExecuteResult(ControllerContext context);
4: }
5:
6: public class StaticViewResult: ActionResult
7: {
8: public override void ExecuteResult(ControllerContext context)
9: {
10: context.RequestContext.HttpContext.Response.WriteFile(context.RequestContext.RouteData.Action + ".html");
11: }
12: }

  七、实例的配置和定义

  在我们的实例中定义的HomeController定义如下,在表示Action的Index方法中,直接返回一个StaticViewResult对象。

1: public class HomeController : DefaultController
2: {
3: public ActionResult Index()
4: {
5: return new StaticViewResult();
6: }
7: }

  然后在配置中进行了针对UrlRoutingModule的注册,仅此而已。

1: <configuration>
2: <system.webServer>
3: <modules>
4: <add name="UrlRoutingModule" type="Artech.MvcRouting.UrlRoutingModule, Artech.MvcRouting"/>
5: </modules>
6: </system.webServer>
7: </configuration>
0
相关文章