How can I, when executing a controller action, take a Uri (not the one requested) and invoke the action from the controller that would have been executed had that Uri been the one that was called? I can’t simply redirect to that action as I need it to happen in the same request context.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Assuming you have access to the HttpContext (and I suppose you do since you are asking) you could:
var routeData = new RouteData(); // controller and action are compulsory routeData.Values["action"] = "index"; routeData.Values["controller"] = "foo"; // some additional route parameter routeData.Values["foo"] = "bar"; IController fooController = new FooController(); var rc = new RequestContext(new HttpContextWrapper(HttpContext), routeData); fooController.Execute(rc);
Personally I use this approach for handling errors inside my application. I put this in Application_Error and execute an error controller for custom error pages staying in the context of the initial HTTP request. You could also place complex objects inside the routeData hash and you will get those complex objects back as action parameters. I use this to pass the actual exception that occurred to the error controller action.
UPDATE:
In order to parse an URL to its route data tokens taking into account current routes you could:
var request = new HttpRequest(null, "http://foo.com/Home/Index", "id=1"); var response = new HttpResponse(new StringWriter()); var httpContext = new HttpContext(request, response); var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); var values = routeData.Values; var action = values["action"]; var controller = values["controller"];
Method 2
For the correct answer, I’d prefer do something like this to let MVC handle creating controllers rather than creating myself.
var routeData = new RouteData();
// controller and action are compulsory
routeData.Values["action"] = "index";
routeData.Values["controller"] = "foo";
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
var requestContext = new RequestContext(new HttpContextWrapper(yourHttpContextObject), routeData);
var controller = factory.CreateController(requestContext, "FooController");
try
{
controller.Execute(requestContext);
}
finally
{
factory.ReleaseController(controller);
}
This would assure you that your Foo controller is getting the same behavior as other controllers.
Method 3
Any reason you can’t push the code you are calling into a controller-independent class? Cross-calling controllers sounds like a bit of a WTF to me.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0