[翻译]MVC.创建你自己的IRouteHandler
原文地址:http://weblogs.asp.net/fredriknormen/archive/2007/11/18/asp-net-mvc-framework-create-your-own-iroutehandler.aspx
原文作者: Fredrik N
本文地址:http://www.cnblogs.com/jpwar/archive/2008/02/25/asp-net-mvc-framework-create-your-own-iroutehandler.html
本文译者:第一控制.NET
译注:asp.net mvc的mix8版过不几天就将出炉,还没实验过的兄弟不妨等等。
在我的上一篇博文中,我展示了怎么在the ASP.Net MVC Framework中创建你自己的IControllerFactory;在今天这篇文章中,我将展示怎么创建你自己的IRouteHandler。
这篇文章中的RouteHandler可以代替我写的继承自IControllerFactory的Controller Factory,当然也会在web.config中指定默认的ControllerFactory和ViewFactory 。这里有一部分功能是当前版本的MVC Framework做不到的。
创建你自己的RouteHandler是非常容易的,我们只需要继承IRouteHandler接口并实现GetHttpHandler方法。;)
 public class N2MVCRouteHandler : IRouteHandler
public class N2MVCRouteHandler : IRouteHandler {
{ public IHttpHandler GetHttpHandler(RequestContext requestContext)
   public IHttpHandler GetHttpHandler(RequestContext requestContext) {
   { N2MVCHandler handler = new N2MVCHandler();
       N2MVCHandler handler = new N2MVCHandler(); handler.RequestContext = requestContext;
       handler.RequestContext = requestContext; return handler;
       return handler; }
    } }
}GetHttpHandler方法返回一个IHttpHandler类型。我已经建立了一个IHttpHandler (N2MVCHandler)。N2MVCHandler继承自ASP.Net MVC Framework中封装的MvcHandler。我之所以要继承MvcHandler是因为我不想重写那些不必要的东西。在我的IHttpHandler中我重写了ProcessRequest方法,并且增加了一些代码来为当前的请求创建一个Controller。
 public class N2MVCHandler : MvcHandler
public class N2MVCHandler : MvcHandler {
{ protected override void ProcessRequest(IHttpContext httpContext)
    protected override void ProcessRequest(IHttpContext httpContext) {
    { if (this.RequestContext == null)
       if (this.RequestContext == null) throw new InvalidOperationException("No RequestContext");
          throw new InvalidOperationException("No RequestContext");
 string controllerName = this.GetRequiredString(this.RequestContext.RouteData, "controller");
       string controllerName = this.GetRequiredString(this.RequestContext.RouteData, "controller");
 IController controller = this.CreateController(controllerName);
       IController controller = this.CreateController(controllerName); ControllerContext controllerContext = new ControllerContext(base.RequestContext, controller);
       ControllerContext controllerContext = new ControllerContext(base.RequestContext, controller);
 controller.Execute(controllerContext);
       controller.Execute(controllerContext); }
    }
 private IController CreateController(string controllerName)
    private IController CreateController(string controllerName) {
    { N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
       N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
 IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);
       IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);
 IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);
       IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);
 return controller;
       return controller; }
    } }
}在ProcessRequest方法中,我用CreateController方法为为当前请求创建了一个Controller。在N2MvcHandler 类中的CreateController 方法实例化了一个在web.config中制定的ControllerFactroy。
在这个例子中,我必须用我自己的接口来代替IControllerFactory,因为我希望传递Controller的名字而不是类型。封装在MVC Framework中的MvcHandler 里的ProcessRequest 尝试在没有程序集引用(references assemblies)的情况下定位Controller 然后创建这个类型的Controller 并把他传递给IController。CreateController 方法。但是我认为应该把寻找Controller类型的工作上移到ControllerFactory 中。下面是我的IControllerFactory 接口的具体实现。
 public interface IN2ControllerFactory
public interface IN2ControllerFactory {
{ IController CreateController(RequestContext context, string controllerName);
    IController CreateController(RequestContext context, string controllerName); }
}注意:你仍然可以创建自己的ControllerFactory,但是你必须继承我的接口来代替IControllerFactory,并且你不需要在Global.asax中的Application_Start事件中调用ControllerBuilder.Current.SetDefaultControllerFactory方法来指定你想使用哪个ControllerFactory。这些工作将在web.config中完成。你将在本文稍后看到这些实现。
我觉得在这篇文章中使用Spring.Net和ControllerFactory来创建我的Controller。
 public class N2ControllerFactory : IN2ControllerFactory
public class N2ControllerFactory : IN2ControllerFactory {
{ public IController CreateController(RequestContext context, string controllerName)
    public IController CreateController(RequestContext context, string controllerName) {
    { IResource input = new FileSystemResource(context.HttpContext.Request.MapPath("objects.xml"));
        IResource input = new FileSystemResource(context.HttpContext.Request.MapPath("objects.xml")); IObjectFactory factory = new XmlObjectFactory(input);
        IObjectFactory factory = new XmlObjectFactory(input); IController controller = (IController)factory.GetObject(controllerName, typeof(IController));
        IController controller = (IController)factory.GetObject(controllerName, typeof(IController));
 if (typeof(Controller).IsAssignableFrom(controller.GetType()))
        if (typeof(Controller).IsAssignableFrom(controller.GetType())) {
        { N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
          N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler; ((Controller)controller).ViewFactory = N2ViewFactoryBuilder.GetViewFactory(config.ViewFactory);
          ((Controller)controller).ViewFactory = N2ViewFactoryBuilder.GetViewFactory(config.ViewFactory); }
        }
 return controller;
        return controller; }
    } }
}ControllerFactory的责任是创建Controller 并填充他需要的所有信息,比如本例中的ViewFactory。
IViewFactory的作用是创建一个责任是创建一个View的factory。因为Controller 并不需要实现Controller 基类(Controller base class)所以我将在我的代码中使用一个“代码规则(code policy)”。我将检查创建出来的Controller 是否继承了Controller 类(Controller class)。如果继承了我就创建一个IViewFactory 并把他注入Controller。IController 接口没有ViewFactory 属性,这些信息我们将在Controller基类中得到。
如果我们再回过头来看一遍IHttpHandler (N2MVCHandler)中的CreateContoller 方法,我们来看看他是怎么在web.config中得到ControllerFactory 的。
 private IController CreateController(string controllerName)
private IController CreateController(string controllerName) {
{ N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
    N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
 IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);
    IN2ControllerFactory controllerFactory = N2ControllerFactoryBuilder.GetControllerFactory(config.ControllerFactory);
 IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);
    IController controller = controllerFactory.CreateController(base.RequestContext, controllerName);
 return controller;
    return controller; }
}我用了一些其他的帮助类来创建了一个Controller-的实例,并且ViewFactory在web.config中指定,帮助类里的代码跟这篇文章没什么关系。在MVC Framework公开的ctp发布以后,你可以给我写一个邮件(不是我哦,是原作者),我可以把我的代码发给你。
下面这些是我们在web.config中指定conrollerFactory 和viewFactory的地方。这样我们就可以在web.config中轻松指定自己的ControllerFactory 和ViewFactory 。
 <Nsquared2>
<Nsquared2> <N2MVCSection
    <N2MVCSection controllerFactory="MvcApplication.Models.N2ControllerFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
        controllerFactory="MvcApplication.Models.N2ControllerFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" viewFactory="MvcApplication.Models.N2ViewFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        viewFactory="MvcApplication.Models.N2ViewFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> </Nsquared2>
</Nsquared2>在使用Route 对象的RouteHandler时,我们可以轻松在MVC Framework中更换RouteHandler 。
 RouteTable.Routes.Add(new Route
RouteTable.Routes.Add(new Route {
{ Url = "[controller]/[action]/[id]",
    Url = "[controller]/[action]/[id]", Defaults = new { action = "Index", id = (string)null },
    Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(N2MVCRouteHandler)
    RouteHandler = typeof(N2MVCRouteHandler) });
});在这篇文章中,你应该已经学会了怎么创建你自己的IRouteHandler,和怎么用你自己的ControllerFactory 代替原有的。
 
                    
                



 
    
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号