Richard Edwards
Richard Edwards

Reputation: 103

Directly call ASP.NET controller action from a different controller

I have a situation where I need to redirect to an ASP.NET MVC action in a different controller. I can't use RedirectToAction because I must POST the action's parameters to keep them out of the URL.

I attempted to instantiate and call the other controller's action directly like this:

OtherController myOtherController = new OtherController();
myOtherController.ControllerContext = new ControllerContext(this.ControllerContext.RequestContext, myOtherController);
return await myOtherController.Edit(myGuid);

When I do this, the other controller's code executes, but I end up with this error:

The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.OtherModel_BBCEF7C9378F4C4F097CC08FA2E508B8BD8D865E33093E31959919087A31348E', but this dictionary requires a model item of type 'ThisModel'.

Does anyone know if I can get this working using the current approach? Assuming I must use an HTTP POST action and cannot have parameters in the URL, is there a different approach that you would recommend to achieve this result (other than combining the controllers)?
Edit:
Note that I don't think I can post directly from the client because I would need to nest Html.BeginForm.

Upvotes: 1

Views: 706

Answers (2)

Paul Swetz
Paul Swetz

Reputation: 2254

You should really just be using RedirectToAction to push the browser to the action you want instead of trying to do it like this. As you can see from @Andrei Olariu code a lot of things happen under the hood during the construction of your controller (DI then context and parameter mappings) that really shouldn't be done manually and can easily be screwed up leading to hours wasted wondering why certain things are not behaving as expected.

Upvotes: 1

Andrei Olariu
Andrei Olariu

Reputation: 556

I hope I understood what you're trying to do. This is what I'm successfully using to execute an action on a different controller.

private void ExecuteErrorAction(string action, HttpContextWrapper httpContext, Exception exception)
{
    var routeData = new RouteData();
    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = action;
    routeData.Values["exception"] = exception;

    IController errorController = DependencyResolver.Current.GetService<ErrorController>();
    var context = new RequestContext(httpContext, routeData);
    errorController.Execute(context);
}

I think that in your case this could look like:

private void ExecuteOtherAction(string myGuid, HttpContextWrapper httpContext)
{
    var routeData = new RouteData();
    routeData.Values["controller"] = "OtherController";
    routeData.Values["action"] = "Edit";
    routeData.Values["myGuid"] = myGuid;

    IController otherCntroller = DependencyResolver.Current.GetService<OtherController>();
    var context = new RequestContext(httpContext, routeData);
    otherCntroller.Execute(context);
}

This is assuming that your Edit action on the OtherController takes a string called myGuid as a parameter.

Let me know if this helps.

Upvotes: 0

Related Questions