代码之家  ›  专栏  ›  技术社区  ›  womp

从任意URL手动实例化控制器实例?

  •  14
  • womp  · 技术社区  · 15 年前

    我的技能不及格,我知道我已经看到了这方面的代码,但我找不到。

    什么是获取任意URL、通过ASP.NET MVC路由系统运行它以及引用另一端的控制器实例的最快方法?

    例如,代码执行在某个任意控制器方法中。我想这样做:

    ...
    string myURL = "http://mysite/mycontroller/myaction/myparameters";
    
    RouteData fakeRouteData = new RouteData(Route???, IRouteHandler???)
    RequestContext ctxt = new RequestContext(this.ControllerContext.HttpContext,
                                             fakeRouteData);
    
    ControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
    Controller result = factory.CreateController(ctxt, controllername???)
    

    我正试图得到一个控制器的实例,就像路由系统一样,不管代码在哪里执行。我不清楚在这一点上如何把这些零件装配在一起。虽然我最终会发现它,但我想我可以通过问这里来节省时间;)

    3 回复  |  直到 15 年前
        1
  •  13
  •   Elijah66    15 年前

    隐马尔可夫模型。。。我不知道这是否是最好的解决方案,因为它需要模拟,但也许这会有所帮助。你走对了,一旦你知道控制器的工厂部分就很简单了。 什么 控制器来实例化,所以问题是什么是获取 路由数据 来自任意URL的对象。

    我唯一知道情况的方法是,用moq:

    string url = "~/Account/LogOn";  //trying to create Account controller in default MVC app
    
    RouteCollection rc = new RouteCollection();
    MvcApplication.RegisterRoutes(rc);
    System.Web.Routing.RouteData rd = new RouteData();
    var mockHttpContext = new Moq.Mock<HttpContextBase>();
    var mockRequest = new Moq.Mock<HttpRequestBase>();
    mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
    mockRequest.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(url);
    
    RouteData routeData = rc.GetRouteData(mockHttpContext.Object);
    
    string controllerName = routeData.Values["controller"].ToString();
    
    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
    IController controller = factory.CreateController(this.ControllerContext.RequestContext, controllerName);
    

    我做了很多谷歌搜索,找不到与单元测试/模拟无关的东西。我不知道那里有没有 一个快速和容易做到这一点,但肯定想知道是否有人有更好的解决方案!

        2
  •  10
  •   womp    15 年前

    好吧,在这工作了几个星期之后,这就是我最后的结果。它就像一个魅力,避免依赖于嘲弄,但仍然让我觉得黑客。

    // Get the application's route collection.
    UrlRoutingModule module = new UrlRoutingModule();
    RouteCollection col = module.RouteCollection;
    
    // Fake a request to the supplied URL into the routing system
    string originalPath = this.HttpContext.Request.Path;
    this.HttpContext.RewritePath(urlToGetControllerFor);
    RouteData fakeRouteData = col.GetRouteData(this.HttpContext);
    
    // Get an instance of the controller that would handle this route
    string controllername = fakeRouteData.Values["controller"].ToString();
    var ctxt = new RequestContext(this.ControllerContext.HttpContext, fakeRouteData);
    IController controller = ControllerBuilder.Current.GetControllerFactory()
                              .CreateController(ctxt, controllername);
    
    // Reset our request path.
    this.HttpContext.RewritePath(originalPath.ToString());
    

    到目前为止,没有绝对的下游副作用 RewritePath() 电话。感谢库尔特的代码,如果有人能想出更好的办法,请不要犹豫,张贴。

        3
  •  0
  •   MisterJames    15 年前

    很明显,你的意思是MVC站点上的任何一个后域URL字符串,对吧?所以,在 http://yourdomain/something/thatSomeone/might/type/here 你的意思是某人/可能/类型/这里部分。

    转到registerroutes方法中的global.asax.ca文件,并添加如下内容:

    routes.MapRoute("foo", "foo/bar/in/a/jar", new { controller = "Home", action = "Index", id = "" });
    

    现在有人输入 http://yourdoamin/foo/bar/in/a/jar 它们将被路由到主/索引控制器操作。

    希望有帮助。

    干杯, JC