谁能告诉我如何从动作方法中调用不同控制器上的方法?我不想重定向。我想在返回字符串的不同控制器上调用一个方法,并在我的操作方法中使用响应。
7 回答
在我看来,您应该重构您的应用程序,并将生成字符串的功能提取到一个新的单独类中(或重用现有类,如果您有一个合适的类)并让两个控制器都使用该类。
您可以使用以下方法调用另一个控制器上的方法:
var otherController = DependencyResolver.Current.GetService<OtherController>();
var result = otherController.SomeMethod();
这在 ASP.NET MVC5 中对我有用。希望它也对你有用。
您可以通过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>
您可以在您的操作方法中实例化控制器并调用您需要的其他方法吗?
public ActionResult YourActionMethod()
{
SomeController c = new SomeController();
ActionResult result = c.SomeMethod();
return View();
}
我没有使用 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 模板,它就什么都不是。
看起来你正在尝试做一些控制器不是为之设计的事情。将您需要的方法设计为某个类中的公共方法,并从两个控制器操作中调用。
我一直在寻找同样的东西,但认真的人,为什么需要写这么复杂的答案。
这是一篇非常简单的回答: 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" })