Can anybody tell me how to call a method on a different controller from within an action method? I don't want to redirect. I want to call a method on a different controller that returns a string and use the response within my action method.
-
1What is the context? There may be a better way of acheiving what you want. – Simon Fox Aug 18 '09 at 21:45
-
1I'm using IoC and have all of the data access going through my controllers. I want to retrieve a specific piece of user data that is available through a different controller. – user135498 Aug 18 '09 at 22:01
-
1I don't know alot about IoC, but maybe moving your method to an ActionFilter could help you do what you want http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx This follows the principles of IoC in my understanding of it – Simon Fox Aug 18 '09 at 22:56
-
What version of MVC are you referring to? – Drew Noakes Dec 05 '10 at 16:28
7 Answers
Sounds in my ears like you should refactor your application, and extract the functionality that generates the string out to a new seperate class (or reuse an existing class, if you have one that fits) and let both controllers use that class.

- 12,206
- 8
- 54
- 70
-
1also known as a Service Layer. (http://martinfowler.com/eaaCatalog/serviceLayer.html) http://wiki.sharparchitecture.net/SettingUpNorthwind.ashx – Visionary Software Solutions Oct 22 '10 at 18:25
-
12Perhaps the string he wants to generate is a HTML string that's already being build by a different controller. Consider the example of feeding this string then into an HTML to PDF generator. Invoking a controller action and capturing the view result in a string sounds to me like a good way to do that. – pettys Apr 20 '11 at 13:57
-
2Just a thought: Make a "SuperController" that both inherit from, and stick the common functionality in there.. – user230910 Apr 12 '15 at 06:41
You can use the following approach to invoke a method on the other controller:
var otherController = DependencyResolver.Current.GetService<OtherController>();
var result = otherController.SomeMethod();
This worked for me in ASP.NET MVC5. Hope that it will work for you as well.
-
3The problem with this, is that there is no Context. So If you're using, say "Server.MapPath(...." for instance, it will error because Server is nothing. – Ed DeGagne Sep 30 '16 at 19:03
You can achieve this via the Action
method of HtmlHelper
.
In a view, you would do it like this:
@Html.Action("OtherAction")
However it's not straightforward to obtain an instance of HtmlHelper
in an action method (by design). In fact it's such a horrible hack that I am reluctant to even post it...
var htmlHelper = new HtmlHelper(new ViewContext(
ControllerContext,
new WebFormView(ControllerContext, "HACK"),
new ViewDataDictionary(),
new TempDataDictionary(),
new StringWriter()),
new ViewPage());
var otherViewHtml = htmlHelper.Action("ActionName", "ControllerName");
This works on MVC 3. You might need to remove the StringWriter
arg from the ViewContext
constructor for MVC 2, IIRC.
</hack>

- 5,164
- 2
- 22
- 36

- 300,895
- 165
- 679
- 742
-
1To get the 'Action' method, you also need to add a using reference to System.Web.Mvc.Html. – JasonRShaver May 14 '12 at 20:18
-
-
dan, you get it from the current controller, that is the one you are calling the other controller from... – Michiel Cornille Aug 01 '12 at 12:35
-
Again, the question was how to call a method in a controller from another controller. This answer has nothing to do with the question. – Ed DeGagne Sep 30 '16 at 19:06
Could you just instantiate the controller in your action method and call the other method you need?
public ActionResult YourActionMethod()
{
SomeController c = new SomeController();
ActionResult result = c.SomeMethod();
return View();
}

- 5,848
- 4
- 28
- 33
-
1The caviet is I'm using Castle Windsor IoC that injects the connection string for the data context. I'm struggling because the the mvc framework automatically intantiates the controller. – user135498 Aug 18 '09 at 21:52
I haven't used Castle Windsor IoC, but the theory is that you should be able to create a custom Controller factory class, and then instruct the MVC framework to use this custom controller factory, by registering it in the Global.asax.css file, in the Application_Start event:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactor());
}
[See Pro Asp.Net MVC 2 Framework, Steven Sanderson, Apress, pages 64 - 66]
That way, you can instantiate your controllers from anywhere in your code.
The notion of NOT calling the actions of another controller from the "current" controller, or from other code is quite wrong. Controllers are just classes. They only become "Controllers" when invoked in a special way by the MVC Framework.
Therefore, the right and wrong of this boils down to WHY are you doing this, not WHETHER you should or not.
If you are just using a controller as a class, then this is fine. If you are trying to use this to send a response to the user, then you should use a RedirectToAction as suggested above.
There are a number of reasons to use a controller as a class rather than as a Controller. For example, when testing your controller. Therefore, treating your controllers from as a class is necessary as opposed to wrong.
A non testing scenario example of using a Controller as a Class:
I am writing a mini framework that leverages the MVC framework's templating capabilities to produce the HTML for HTML emails, something that all web apps need to do, for one reason or another (eg, order confirmation emails).
Very roughly, you instantiate your MailManagerController (for simplicity, presume you are not using IoC) in your NormalController's action (that needs to send an email) and then do:
MailManagerController mailmanager = new MailManagerController();
string html = mailmanager.OrderConfirmation(order).RenderToString();
Postman.SendEmail(html, order.UserEmailAddress, "MyApp order confirmation");
Where RenderToString is an extension method on ViewResultBase that renders the output of an Action (that returns a ViewResultBase object) to a string, and Postman is a static class that deals with sending emails once you have the text.
The beauty of this technique is that you can use the MVC framework to produce templated emails, because the OrderConfirmation Action will have an associated view which is nothing if not an html template for your the email you are going to send.

- 13,481
- 10
- 83
- 129
-
2"Therefore, the right and wrong of this boils down to WHY are you doing this, not WHETHER you should or not." One could argue very differently. Common functionality often can and should be refactored into a Service Layer. (http://martinfowler.com/eaaCatalog/serviceLayer.html) This logical partitioning is seen in many places, including the Grails MVC technology stack (see the excellent book, Grails in Action) (http://www.grails.org/doc/1.0.x/guide/8.%20The%20Service%20Layer.html) and the SharpArchitecture .NET stack (http://wiki.sharparchitecture.net/SettingUpNorthwind.ashx) – Visionary Software Solutions Oct 22 '10 at 18:19
-
Additionally, one could argue that the MailManagerController here should be an Application Service that is injected into a controller. Using the principles of IoC: pubilc ActionResult SendMail() { mailService.sendMail(new OrderConfirmation(order)); // assume service has been injected by IoC container } – Visionary Software Solutions Oct 22 '10 at 18:23
-
I'm approaching a similar need - one little select bit of functionality from one controller's action. In fact, specifically regards a Mail Manager role. It would be helpful to hear more thoughts on the merits of the above approaches. – justSteve Nov 30 '10 at 18:52
-
@justSteve, I posted an answer that shows how to do this within a controller. It's pretty ugly, but it's the best you'll get, afaik. – Drew Noakes Dec 05 '10 at 17:08
Looks like you're trying to do something the controllers aren't designed for. Design your required method as an public method in some class and invoke from both controller actions.

- 3,122
- 2
- 26
- 36
-
This is also known as an Application Service. (http://wiki.sharparchitecture.net/SettingUpNorthwind.ashx) It typically belongs in a Service Layer, though you could refactor down into the Domain Model is the methods are Domain Object Specific. (http://martinfowler.com/eaaCatalog/serviceLayer.html) – Visionary Software Solutions Oct 22 '10 at 18:17
I was looking for the same thing, but seriously people, why the need to write such complicated answers.
Here's a post that will answer it very simply: Using Html.ActionLink to call action on different controller
Basically you just have to use this overload of the actionlink:
ActionLink(HtmlHelper, String, String, String, Object, Object)
So you will have:
ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)
If you don't have any routeValues (which are the Inputs for the Action) or htmlAttributes, you have to set them as null.
Here's an example call:
@Html.ActionLink("Add New Student", "Create", "Student", null, new { @class = "btn btn-primary" })
-
4
-
Unfortunately, this answer has zero to do with the actual question. – Ed DeGagne Sep 30 '16 at 19:04