不同控制器上的.NET MVC调用方法

时间:2009-08-18 21:38:25

标签: .net asp.net-mvc action

有人能告诉我如何在动作方法中调用不同控制器上的方法吗?我不想重定向。我想在不同的控制器上调用一个方法,该控制器返回一个字符串并在我的action方法中使用响应。

7 个答案:

答案 0 :(得分:42)

听起来像你应该重构你的应用程序,并将生成字符串的功能提取到一个新的单独类(或重用现有的类,如果你有一个适合)并让两个控制器使用该类。

答案 1 :(得分:22)

您可以使用以下方法在另一个控制器上调用方法:

var otherController = DependencyResolver.Current.GetService<OtherController>();
var result = otherController.SomeMethod();

这在ASP.NET MVC5中对我有用。希望它也适合你。

答案 2 :(得分:12)

你能在动作方法中实例化控制器并调用你需要的其他方法吗?

public ActionResult YourActionMethod()
{
   SomeController c = new SomeController();
   ActionResult result = c.SomeMethod();

   return View();
}

答案 3 :(得分:11)

您可以通过HtmlHelper的{​​{3}}方法实现此目的。

在视图中,您可以这样做:

@Html.Action("OtherAction")

然而,在动作方法中(按设计)获取HtmlHelper的实例并不简单。事实上,这是一个非常可怕的黑客,我甚至不愿发布它......

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

这适用于MVC 3.您可能需要从MVC 2,IIRC的StringWriter构造函数中删除ViewContext arg。

&LT; /劈&GT;

答案 4 :(得分:9)

我没有使用Castle Windsor IoC,但理论上你应该能够创建一个自定义的Controller工厂类,然后通过在Global.asax中注册它来指示MVC框架使用这个自定义控制器工厂。 .css文件,在Application_Start事件中:

protected void Application_Start()
{
   RegisterRoutes(RouteTable.Routes);
   ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactor());
}

[参见Pro Asp.Net MVC 2框架,Steven Sanderson,Apress,第64-66页]

这样,您可以从代码中的任何位置实例化控制器。

NOT从“当前”控制器或其他代码调用另一个控制器的操作的概念是非常错误的。控制器只是类。它们只有在MVC框架以特殊方式调用时才会成为“控制器”。

因此,这的正确与错误归结为你为什么这样做,而不是你应该与否。

如果您只是将控制器用作类,那么这很好。如果您尝试使用此方法向用户发送响应,则应使用上面建议的RedirectToAction。

将控制器用作类而不是控制器有很多原因。例如,在测试控制器时。因此,将控制器视为一个类是必要的而不是错误。

将Controller用作类的非测试场景示例:

我正在编写一个迷你框架,利用MVC框架的模板功能来生成HTML电子邮件的HTML,这是所有网络应用程序需要做的事情,原因之一(例如,订单确认电子邮件)。

非常粗略地说,您在NormalController的操作(需要发送电子邮件)中实例化您的MailManagerController(为简单起见,假设您没有使用IoC),然后执行:

MailManagerController mailmanager = new MailManagerController();
string html = mailmanager.OrderConfirmation(order).RenderToString();
Postman.SendEmail(html, order.UserEmailAddress, "MyApp order confirmation");

其中RenderToString是ViewResultBase上的一个扩展方法,它将Action的输出(返回一个ViewResultBase对象)呈现给一个字符串,而Postman是一个静态类,它处理一旦你有了文本就发送电子邮件。

这种技术的优点在于你可以使用MVC框架来生成模板化的电子邮件,因为OrderConfirmation Action将有一个关联的视图,如果不是你要发送的电子邮件的html模板,那就什么都不是。

答案 5 :(得分:2)

看起来你正试图做一些控制器不适合的事情。 将所需方法设计为某个类中的公共方法,并从两个控制器操作中调用。

答案 6 :(得分:-6)

我一直在寻找同样的东西,但是认真的人,为什么需要写出如此复杂的答案。

这是一篇非常简单的回答: Using Html.ActionLink to call action on different controller

基本上你只需要使用actionlink的这个重载: ActionLink(HtmlHelper, String, String, String, Object, Object)

所以你会: ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)

如果您没有任何routeValues(Action的输入)或htmlAttributes,则必须将它们设置为null。

以下是一个示例电话: @Html.ActionLink("Add New Student", "Create", "Student", null, new { @class = "btn btn-primary" })