How to call another controller Action From a controller in Mvc
Clash Royale CLAN TAG#URR8PPP
How to call another controller Action From a controller in Mvc
I need to call a controller B action FileUploadMsgView from Controller A and need to pass a parameter for it.
Code---its not going to the controller B's FileUploadMsgView().
In ControllerA
private void Test()
{
try
//some codes here
ViewBag.FileUploadMsg = "File uploaded successfully.";
ViewBag.FileUploadFlag = "2";
RedirectToAction("B", "FileUploadMsgView", new FileUploadMsg = "File uploaded successfully" );
In ControllerB receiving part
public ActionResult FileUploadMsgView(string FileUploadMsg)
return View();
@AndersM. Ed's answer does a redirect. That is not what I want when I found this question searching for a solution.
– mxmissile
Dec 12 '14 at 17:07
@mxmissile not to be a dick but Ed's answer is what the asker needs since he wants a view that is returned based on what is uploaded, I agree that asker could have done a better job at formulating his question(is this the right word?) we can't know this though as his english may be limited, even though Tiesons answer helped you - which is good - it doesn't change the fact that Ed's answer best reflects what the asker needs
– Anders M.
Dec 16 '14 at 15:16
@AndersM. I understand, my comment wording was just bad... :-) I should have emphasized the point that was not the result I desired.
– mxmissile
Dec 16 '14 at 16:30
@AndersM. The asker accepted the answer of Tieson as best, so I'm not sure why you would decide for him? The answer Tieson gave me helped me more then the answer Ed's answer. SO is not just for helping a single person, but everyone who has similar problems. So why not just keep Tieson's answer on top?
– Kevin Voorn
Dec 19 '14 at 13:57
9 Answers
9
Controllers are just classes - new one up and call the action method just like you would any other class member:
var result = new ControllerB().FileUploadMsgView("some string");
var result = new ControllerB().FileUploadMsgView("some string");
Won't you be missing ControllerContext, Request and friends if you just do this?
– cirrus
Oct 15 '13 at 10:37
The instantiation of controller is not a good idea because it's life cycle might be controlled by another part of the application. E.g. when using an IoC container all depdencies should be injected, etc.
– Mo Valipour
Nov 25 '13 at 16:37
If your using IoC, you can get a populated controller via
var controller = DependencyResolver.Current.GetService<ControllerB>();
– mxmissile
Dec 12 '14 at 17:11
var controller = DependencyResolver.Current.GetService<ControllerB>();
@mxmissile That's worth adding as a new answer, rather than a comment here.
– Tieson T.
Dec 13 '14 at 3:15
@ilasno Are you familiar with the term "inversion of control"? The point he's making is that if you have components in your controllers that need to be injected into the constructor, my answer doesn't really work, unless you use something like the DependencyResolver as a service-locator.
– Tieson T.
Dec 11 '16 at 18:26
As @mxmissile says in the comments to the accepted answer, you shouldn't new up the controller because it will be missing dependencies set up for IoC and won't have the HttpContext
.
HttpContext
Instead, you should get an instance of your controller like this:
var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);
Exactly what I was looking for. Note that those not using IoC still won't get an
HttpContext
injected.– brichins
Aug 28 '15 at 21:34
HttpContext
var stands for ControllerB right?
– Willa
Feb 2 '16 at 13:15
This gets me close, but one problem that arises is that in my case, controller.MyAction() makes reference to User.Identity which appears to be uininstantiated.
– Robert H. Bourdeau
May 25 '16 at 17:10
@ilasno I'm rusty on MVC these days, but I think I meant that you have to actually have IoC set up to get a fully populated Controller object (e.g. an associated
HttpContext
). I believe I used this approach without any IoC to get a "shallow" controller object (just needed access to certain functionality) and was initially confused about why parts were "missing". [aside: I worked around it while still using this approach, but probably should have refactored that functionality out to a shared class.] As for IoC setup and choices, I'd have to refer you to other articles / SO questions.– brichins
Dec 12 '16 at 19:59
HttpContext
Some people get carried away with pointless edits... note that someone edited the answer changing the variable "controller" to "ctrlr"... so it should read "ctrlr.ControllerContext = new ControllerContext(this.Request.RequestContext, ctrl);" if that user edited it correctly
– JoeSharp
Dec 27 '17 at 15:10
Your sample looks like psuedo code. You need to return the result of RedirectToAction
:
RedirectToAction
return RedirectToAction("B",
"FileUploadMsgView",
new FileUploadMsg = "File uploaded successfully" );
It must be pointed out that if the target action accepts POST only, this won't work.
– Marco Alves
Jul 25 '14 at 19:09
This returns a 302 which causes another hit to the server which is not what the question asks.
– rboarman
Feb 17 '15 at 0:42
@rboarman and I get 404
– usefulBee
Jun 16 '16 at 17:25
as @DLeh says
Use rather
var controller = DependencyResolver.Current.GetService<ControllerB>();
But, giving the controller, a controlller context is important especially when you need to access the User
object, Server
object, or the HttpContext
inside the 'child' controller.
User
Server
HttpContext
I have added a line of code:
controller.ControllerContext = new ControllerContext(Request.RequestContext, controller);
or else you could have used System.Web to acces the current context too, to access Server
or the early metioned objects
Server
NB: i am targetting the framework version 4.6 (Mvc5)
If you try to call an action in the controller which uses View(..) or PartialView(...) you need to manually change the routeData, so that ASP.NET knows how to find your view.
controller.RouteData.Values["controller"] = "Home";controller.RouteData.Values["action"] = "Index";
Assuming you are trying to return the result from the Index action in HomeController.– Steven
Jun 18 '16 at 1:28
controller.RouteData.Values["controller"] = "Home";controller.RouteData.Values["action"] = "Index";
@Steven I had to apply these values to
this
rather than controller
. Ultimately the result comes back through the local controller (this) so that's what ends up trying to find the view.– aaaantoine
Aug 29 '16 at 13:36
this
controller
I'd add also that Url property isn't initialized upon DependencyResolver.Current.GetService<ControllerB>(). So you have to copy it from current controller manually.
– Ralfeus
Feb 7 '17 at 10:35
In the targeting Action you should use
return View("ViewName");
instead just return View();
– mNejkO
Mar 12 '17 at 23:52
return View("ViewName");
return View();
Let the resolver automatically do that.
Inside A controller:
public class AController : ApiController
private readonly BController _bController;
public AController(
BController bController)
_bController = bController;
public httpMethod
var result = _bController.OtherMethodBController(parameters);
....
imo the cleanest answer, but you should set the controller context to the new controller.
– Mafii
Jun 26 '17 at 13:26
Dleh's answer is correct and explain how to get an instance of another controller without missing dependencies set up for IoC
However, we now need to call the method from this other controller.
Full answer would be :
var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);
//Call your method
ActionInvoker.InvokeAction(controller.ControllerContext, "MethodNameFromControllerB_ToCall");
This is exactly what I was looking for after finding that RedirectToAction()
would not pass complex class objects.
RedirectToAction()
As an example, I want to call the IndexComparison
method in the LifeCycleEffectsResults
controller and pass it a complex class object named model.
IndexComparison
LifeCycleEffectsResults
Here is the code that failed:
return RedirectToAction("IndexComparison", "LifeCycleEffectsResults", model);
Worth noting is that Strings, integers, etc were surviving the trip to this controller method, but generic list objects were suffering from what was reminiscent of C memory leaks.
As recommended above, here's the code I replaced it with:
var controller = DependencyResolver.Current.GetService<LifeCycleEffectsResultsController>();
var result = controller.IndexComparison(model);
return result;
All is working as intended now. Thank you for leading the way.
if the problem is to call.
you can call it using this method.
yourController obj= new yourController();
obj.yourAction();
Pfft! What if you're expecting a result from an action instead?
var res = new ControllerB().SetUpTimer(new TimeSpan(23, 20, 00));
– user5173426
Mar 29 at 9:49
var res = new ControllerB().SetUpTimer(new TimeSpan(23, 20, 00));
public ActionResult First_controller()
return Redirect("~/File_upload/Second_controller");
public ActionResult Second_controller()
return View();
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I know this question is old but in my opinion you should mark the answer from ed chapel as the best one, tieson's looks like a hack, it's still valid, but why use a workaround when you can use it the way it was meant to be and get the desired result
– Anders M.
Feb 28 '14 at 14:00