Создание экземпляра Controller вручную с произвольного URL-адреса? - PullRequest
14 голосов
/ 14 января 2010

Мои навыки подводят меня, и я знаю, что видел код для этого, но не могу его найти.

Какой самый быстрый способ взять любой произвольный URL, запустить его через систему маршрутизации mvc asp.net и получить ссылку на экземпляр контроллера на другом конце? Например, выполнение кода внутри какого-то произвольного метода контроллера. Я хочу сделать что-то вроде этого:

...
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 ]

13 голосов
/ 14 января 2010

Хм ... Я не знаю, является ли это лучшим решением, потому что оно требует насмешек, но, возможно, это поможет. Вы на правильном пути, и заводская часть контроллера проста, когда вы знаете, какой контроллер создается, поэтому вопрос в том, какой самый быстрый способ получить объект RouteData из произвольного 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);

Я немного погуглил и не смог найти ничего, что не относилось к юнит-тестированию / издевательствам. Я не знаю, если это , это быстро и легко сделать это, но, конечно, хотел бы знать, если у кого-то есть лучшее решение!

10 голосов
/ 29 января 2010

Хорошо, после работы с этим в течение пары недель, это то, что я закончил. Он работает как шарм и избегает зависимостей от насмешек, но все же мне кажется хакерским.

// 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(). Спасибо Курту за его код, и если кто-то может придумать что-нибудь получше, пожалуйста, не стесняйтесь писать.

0 голосов
/ 14 января 2010

Очевидно, что вы имеете в виду любую строку URL-адреса постдомена на сайте MVC, верно? Итак, в http://yourdomain/something/thatSomeone/might/type/here вы имеете в виду что-то / thatSomeone / might / type / here.

Перейдите к файлу Global.asax.ca в методе RegisterRoutes и добавьте что-то вроде следующего:

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

Теперь, когда кто-то наберет http://yourdoamin/foo/bar/in/a/jar, он будет перенаправлен на действие контроллера Home / Index.

Надеюсь, это поможет.

Cheers, -jc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...