如何调用另一个控制器操作从Mvc中的控制器

use*_*088 140 c# asp.net-mvc asp.net-mvc-4

我需要从Controller A调用控制器B动作FileUploadMsgView并需要为它传递一个参数.

 Code---its not going to the controller B's FileUploadMsgView().
    In ControllerA
  private void Test()
    {

        try
        {//some codes here
            ViewBag.FileUploadMsg = "File uploaded successfully.";
            ViewBag.FileUploadFlag = "2";

            RedirectToAction("B", "FileUploadMsgView", new { FileUploadMsg = "File   uploaded successfully" });
        }

     In ControllerB receiving part
  public ActionResult FileUploadMsgView(string FileUploadMsg)
    {
         return View();
    }
Run Code Online (Sandbox Code Playgroud)

DLe*_*Leh 178

正如@mxmissile在对已接受答案的评论中所说的那样,你不应该新建控制器,因为它将缺少为IoC设置的依赖关系而不会有HttpContext.

相反,您应该得到一个控制器的实例,如下所示:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);
Run Code Online (Sandbox Code Playgroud)

  • 有些人被无意义的编辑带走......注意有人编辑了答案,将变量"controller"改为"ctrlr"...所以它应该读作"ctrlr.ControllerContext = new ControllerContext(this.Request.RequestContext,ctrl) ;" 如果该用户正确编辑它 (2认同)

Tie*_* T. 98

控制器只是类 - 新的一个并且像调用其他类成员一样调用action方法:

var result = new ControllerB().FileUploadMsgView("some string");

  • 如果你这样做,你不会错过ControllerContext,Request和朋友吗? (68认同)
  • 如果你使用IoC,你可以通过`var controller = DependencyResolver.Current.GetService <ControllerB>()获得一个填充的控制器;` (47认同)
  • 控制器的实例化不是一个好主意,因为它的生命周期可能由应用程序的另一部分控制.例如,当使用IoC容器时,应注入所有依赖性等. (14认同)
  • @mxmissile这是值得添加的新答案,而不是这里的评论. (2认同)
  • @ilasno你熟悉"控制倒置"一词吗?他要说的是,如果你的控制器中有需要注入构造函数的组件,我的答案就不会真正起作用,除非你使用像DependencyResolver这样的服务定位器. (2认同)

Ed *_*pel 61

您的示例看起来像psuedo代码.您需要返回以下结果RedirectToAction:

return RedirectToAction("B", 
                        "FileUploadMsgView",
                        new { FileUploadMsg = "File uploaded successfully" });
Run Code Online (Sandbox Code Playgroud)

  • 这返回302,这导致另一个命中服务器,这不是问题所要求的. (11认同)
  • 必须指出的是,如果目标操作仅接受POST,则不起作用. (4认同)

Nis*_*aan 16

正如@DLeh所说的那样

var controller = DependencyResolver.Current.GetService<ControllerB>();
Run Code Online (Sandbox Code Playgroud)

但是,给控制器一个控制器上下文非常重要,尤其是当您需要访问User对象,Server对象或HttpContext"子"控制器内部时.

我添加了一行代码:

controller.ControllerContext = new ControllerContext(Request.RequestContext, controller);
Run Code Online (Sandbox Code Playgroud)

或者您也可以使用System.Web访问当前上下文,访问Server或早期提到的对象

注意:我的目标是框架版本4.6(Mvc5)

  • 如果您尝试在使用V​​iew(..)或PartialView(...)的控制器中调用操作,则需要手动更改routeData,以便ASP.NET知道如何查找视图.`controller.RouteData.Values [ "控制器"] = "家"; controller.RouteData.Values [ "行动"] = "指数";`假设你正在试图返回从HomeController中Index操作的结果. (4认同)

Dav*_*tro 8

让解析器自动执行此操作.

内部A控制器:

public class AController : ApiController
{
    private readonly BController _bController;

    public AController(
    BController bController)
    {
        _bController = bController;
    }

    public httpMethod{
    var result =  _bController.OtherMethodBController(parameters);
    ....
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 即使是最干净的答案,但您应该将控制器上下文设置为新控制器. (2认同)
  • 不要忘记 services.AddMvc().AddControllersAsServices(); 在 Startup.cs 中 (2认同)

Wat*_*tth 7

我知道它很旧,但你可以:

  • 创建服务层
  • 在那里移动方法
  • 两个控制器中的调用方法


Ogg*_*las 6

如果您使用 .NET Core 或 .NET 5 < 您可以这样做:

中层控制器:

services.AddMvc().AddControllersAsServices();
Run Code Online (Sandbox Code Playgroud)

ApiController

services.AddControllers().AddControllersAsServices();
Run Code Online (Sandbox Code Playgroud)

然后你可以像任何其他服务一样简单地注入你的控制器


小智 5

This is exactly what I was looking for after finding that RedirectToAction() would not pass complex class objects.

As an example, I want to call the IndexComparison method in the LifeCycleEffectsResults controller and pass it a complex class object named model.

Here is the code that failed:

return RedirectToAction("IndexComparison", "LifeCycleEffectsResults", model);
Run Code Online (Sandbox Code Playgroud)

Worth noting is that Strings, integers, etc were surviving the trip to this controller method, but generic list objects were suffering from what was reminiscent of C memory leaks.

As recommended above, here's the code I replaced it with:

var controller = DependencyResolver.Current.GetService<LifeCycleEffectsResultsController>();

var result = controller.IndexComparison(model);
return result;
Run Code Online (Sandbox Code Playgroud)

All is working as intended now. Thank you for leading the way.


小智 5

如果问题是打电话。你可以使用这个方法来调用它。

yourController obj= new yourController();

obj.yourAction();
Run Code Online (Sandbox Code Playgroud)

  • 噗!如果您期望某个操作得到结果怎么办?`var res = new ControllerB().SetUpTimer(new TimeSpan(23, 20, 00));` (2认同)

Ale*_*exB 5

Dleh 的回答是正确的,并解释了如何在不丢失为 IoC 设置的依赖项的情况下获取另一个控制器的实例

但是,我们现在需要从另一个控制器调用该方法。
完整的答案是:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);

//Call your method
ActionInvoker.InvokeAction(controller.ControllerContext, "MethodNameFromControllerB_ToCall");
Run Code Online (Sandbox Code Playgroud)

  • 如果需要参数,如何调用操作“MethodNameFromControllerB_ToCall”?例如 MethodNameFromControllerB_ToCall(int somenum, string sometext)? (2认同)

Leo*_*chi 5

如果有人正在寻找如何在.net核心中执行此操作,则可以通过在启动时添加控制器来完成此操作

services.AddTransient<MyControllerIwantToInject>();
Run Code Online (Sandbox Code Playgroud)

然后将其注入另一个控制器

public class controllerBeingInjectedInto : ControllerBase
{
    private readonly MyControllerIwantToInject _myControllerIwantToInject

     public controllerBeingInjectedInto(MyControllerIwantToInject myControllerIwantToInject)
{
       _myControllerIwantToInject = myControllerIwantToInject;
      }
Run Code Online (Sandbox Code Playgroud)

然后像这样称呼它 _myControllerIwantToInject.MyMethodINeed();