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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1296680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:10:47  来源:igfitidea点击:

.NET MVC Call method on different controller

.netasp.net-mvcaction

提问by user135498

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.

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

回答by Pete

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.

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

回答by Pete

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.

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

回答by Drew Noakes

You can achieve this via the Actionmethod of HtmlHelper.

您可以通过 的Action方法实现这一点HtmlHelper

In a view, you would do it like this:

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

@Html.Action("OtherAction")

However it's not straightforward to obtain an instance of HtmlHelperin an action method (by design). In fact it's such a horrible hack that I am reluctant to even post it...

但是,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");

This works on MVC 3. You might need to remove the StringWriterarg from the ViewContextconstructor for MVC 2, IIRC.

这适用于 MVC 3。您可能需要StringWriterViewContextMVC 2 IIRC的构造函数中删除arg 。

</hack>

</hack>

回答by Nick

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

回答by awrigley

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:

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

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]

[参见 Pro Asp.Net MVC 2 框架,Steven Sanderson,Apress,第 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.

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

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.

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

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

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

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:

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

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.

其中 RenderToString 是 ViewResultBase 上的一个扩展方法,它将 Action 的输出(返回一个 ViewResultBase 对象)呈现为一个字符串,而 Postman 是一个静态类,用于在您获得文本后处理发送电子邮件。

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.

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

回答by twk

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.

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

回答by user2965640

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

这是一篇可以非常简单地回答的帖子: 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)

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

So you will have: ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)

所以你将拥有: 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.

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

Here's an example call: @Html.ActionLink("Add New Student", "Create", "Student", null, new { @class = "btn btn-primary" })

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