简体   繁体   中英

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 .

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM