47

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

4

7 回答 7

42

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

于 2009-08-20T07:07:32.007 回答
23

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

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

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

于 2014-12-04T10:16:25.813 回答
13

您可以通过Action.HtmlHelper

在一个视图中,你会这样做:

@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 IIRCStringWriter的构造函数中删除 arg 。ViewContext

</hack>

于 2010-12-05T17:07:19.193 回答
10

您可以在您的操作方法中实例化控制器并调用您需要的其他方法吗?

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

   return View();
}
于 2009-08-18T21:41:57.987 回答
9

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

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

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

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

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

因此,这件事的对错归结为你为什么要这样做,而不是你是否应该这样做。

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

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

使用控制器作为类的非测试场景示例:

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

非常粗略地,您在 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 模板,它就什么都不是。

于 2010-09-17T13:47:39.507 回答
2

看起来你正在尝试做一些控制器不是为之设计的事情。将您需要的方法设计为某个类中的公共方法,并从两个控制器操作中调用。

于 2009-08-18T21:48:53.497 回答
-6

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

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

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

所以你将拥有: ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)

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

这是一个示例调用: @Html.ActionLink("Add New Student", "Create", "Student", null, new { @class = "btn btn-primary" })

于 2014-04-29T14:18:36.397 回答