169
votes

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();
    }
10
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 resultAnders M.
@AndersM. Ed's answer does a redirect. That is not what I want when I found this question searching for a solution.mxmissile
@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 needsAnders M.
@AndersM. I understand, my comment wording was just bad... :-) I should have emphasized the point that was not the result I desired.mxmissile
@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

10 Answers

117
votes

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");

235
votes

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.

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);
61
votes

Your sample looks like psuedo code. You need to return the result of RedirectToAction:

return RedirectToAction("B", 
                        "FileUploadMsgView",
                        new { FileUploadMsg = "File uploaded successfully" });
17
votes

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.

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

NB: i am targetting the framework version 4.6 (Mvc5)

10
votes

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);
    ....
    }

}
8
votes

If anyone is looking at how to do this in .net core I accomplished it by adding the controller in startup

services.AddTransient<MyControllerIwantToInject>();

Then Injecting it into the other controller

public class controllerBeingInjectedInto : ControllerBase
{
    private readonly MyControllerIwantToInject _myControllerIwantToInject

     public controllerBeingInjectedInto(MyControllerIwantToInject myControllerIwantToInject)
{
       _myControllerIwantToInject = myControllerIwantToInject;
      }

Then just call it like so _myControllerIwantToInject.MyMethodINeed();

7
votes

I know it's old, but you can:

  • Create a service layer
  • Move method there
  • Call method in both controllers
5
votes

This is exactly what I was looking for after finding that RedirectToAction() would not pass complex class objects.

As an example, I want to call the IndexComparison method in the LifeCycleEffectsResults controller and pass it a complex class object named model.

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.

5
votes

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");
2
votes

if the problem is to call. you can call it using this method.

yourController obj= new yourController();

obj.yourAction();