Mvcのコントローラーから別のコントローラーアクションを呼び出す方法


153

コントローラー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();
    }

3
私はこの質問が古いことを知っていますが、私の意見では、エドチャペルからの回答を最良のものとしてマークする必要がありますそして、望ましい結果を得る
Anders M.

1
@AndersM。エドの答えはリダイレクトを行います。解決策を探すこの質問を見つけたとき、それは私が望んでいることではありません。
mxmissile 14

@mxmissileはディックではありませんが、アップロードされた内容に基づいて返されるビューを望んでいるので、エスカの答えは質問者が必要とするものです。 )タイソンズの回答があなたを助けたとしても、彼の英語は限られている可能性があるため、私たちはこれを知ることができません-これは良いことです-それはエドの回答が質問者のニーズを最もよく反映しているという事実を変更しません
Anders M.

2
@AndersM。私は私のコメントの文言だけで悪かった、理解して... :-)私は結果ではなかった点を強調している必要があり、私は希望を。
mxmissile 2014

@AndersM。質問者はTiesonの答えを最もよく受け入れたので、なぜあなたが彼のために決めるのか分かりませんか?Tiesonが私に与えた答えは、Edの答えよりも私を助けてくれました。SOは、1人の人を助けるだけでなく、同様の問題を抱えているすべての人を助けるためのものです。では、なぜTiesonの答えを最優先にしないのですか?
Kevin

回答:


106

コントローラは単なるクラスです-新しいもので、他のクラスメンバーと同じようにアクションメソッドを呼び出します。

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


76
これを行うだけで、ControllerContext、Request、およびフレンドが不足していませんか?
cirrus 2013年

20
コントローラのインスタンス化は、そのライフサイクルがアプリケーションの別の部分によって制御される可能性があるため、良い考えではありません。例えば等、全てdepdenciesが注入されるべきIoCコンテナを使用して、
モリブデンValipour

48
IoCを使用している場合は、次のようにしてコントローラーを取得できますvar controller = DependencyResolver.Current.GetService<ControllerB>();
mxmissile

3
@mxmissileコメントではなく、新しい回答として追加する価値があります。
Tieson T.

2
@ilasno「制御の反転」という用語をご存知ですか?彼が指摘しているのは、コントローラーにコンポーネントを注入する必要があるコンポーネントがある場合、DependencyResolverのようなものをサービスロケーターとして使用しない限り、私の答えは実際には機能しないということです。
Tieson T. 2016

202

承認された回答へのコメントで@mxmissileが言うように、IoC用に設定された依存関係が欠落し、がないため、コントローラーを新規作成しないでくださいHttpContext

代わりに、次のようなコントローラーのインスタンスを取得する必要があります。

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

まさに私が探していたもの。IoCを使用していないユーザーは、まだHttpContext注入されないことに注意してください。
brichins

var controllerControllerBはい、タイプが割り当てられます。
DLeh 16

1
これは私を近づけますが、私の場合、controller.MyAction()が、インスタンス化されていないように見えるUser.Identityを参照するという問題が発生します。
Robert H. Bourdeau 2016年

1
@ilasno私は最近MVCに頼っていますが、実際 IoCを設定して、完全に読み込まれたコントローラーオブジェクト(たとえば、関連付けられたHttpContext)を取得する必要があることを意味します。IoC を使用せずにこのアプローチを使用して「浅い」コントローラーオブジェクトを取得し(特定の機能へのアクセスが必要になっただけ)、最初はパーツが「欠落」している理由について混乱していました。[余談:このアプローチを使用しながら回避しましたが、おそらくその機能を共有クラスにリファクタリングする必要がありました。] IoCのセットアップと選択については、他の記事/ SOの質問を参照する必要があります。
brichins 16

3
無意味な編集に夢中になっている人もいます...誰かが変数 "controller"を "ctrlr"に変更して回答を編集したことに注意してください...したがって、 "ctrlr.ControllerContext = new ControllerContext(this.Request.RequestContext、ctrl) ; " ユーザーが正しく編集した場合
JoeSharp

62

サンプルは擬似コードのように見えます。次の結果を返す必要がありますRedirectToAction

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

4
ターゲットアクションがPOSTのみを受け入れる場合、これは機能しないことを指摘しておく必要があります。
Marco Alves

13
これは302を返し、サーバーに別のヒットを引き起こしますが、これは質問が尋ねるものではありません。
rboarman 2015

16

@DLehが言うようにかなり使用

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

ただし、コントローラーを指定すると、特にUserオブジェクト、Serverオブジェクト、またはHttpContext「子」コントローラーの内部にアクセスする必要がある場合は、コントローラーコンテキストが重要です。

コード行を追加しました:

controller.ControllerContext = new ControllerContext(Request.RequestContext, controller);

または、System.Webを使用して現在のコンテキストにアクセスしServerたり、初期のオブジェクトにアクセスしたりすることもできます

注意:私はフレームワークのバージョン4.6(Mvc5)をターゲットにしています


4
View(..)またはPartialView(...)を使用するコントローラーでアクションを呼び出そうとする場合、ASP.NETがビューを見つける方法を認識できるように、routeDataを手動で変更する必要があります。controller.RouteData.Values["controller"] = "Home";controller.RouteData.Values["action"] = "Index";HomeControllerのIndexアクションから結果を返そうとしていると仮定します。
スティーブン

@Steven thisではなく、これらの値を適用する必要がありましたcontroller。最終的に、結果はローカルコントローラ(this)を介して返されるため、最終的にはビューを見つけようとします。
aaaantoine

また、DependencyResolver.Current.GetService <ControllerB>()でUrlプロパティが初期化されないことも追加します。そのため、現在のコントローラーから手動でコピーする必要があります。
ラルフェウス2017

ターゲットアクションでは、return View("ViewName");代わりに単に使用する必要がありますreturn View();
mNejkO

9

リゾルバーに自動的に実行させます。

コントローラの内部:

public class AController : ApiController
{
    private readonly BController _bController;

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

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

}

2
最もきれいな答えはimoですが、コントローラーコンテキストを新しいコントローラーに設定する必要があります。
マフィイ2017年

8

.netコアでこれを行う方法を誰かが見ている場合、起動時にコントローラーを追加することでそれを達成しました

services.AddTransient<MyControllerIwantToInject>();

次に、それを他のコントローラに注入します

public class controllerBeingInjectedInto : ControllerBase
{
    private readonly MyControllerIwantToInject _myControllerIwantToInject

     public controllerBeingInjectedInto(MyControllerIwantToInject myControllerIwantToInject)
{
       _myControllerIwantToInject = myControllerIwantToInject;
      }

次に、それをそのように呼び出します _myControllerIwantToInject.MyMethodINeed();


4

これは、RedirectToAction()複雑なクラスオブジェクトを渡さないことがわかった後、まさに私が探していたものです。

例として、コントローラーでIndexComparisonメソッドを呼び出して、LifeCycleEffectsResultsmodelという名前の複雑なクラスオブジェクトを渡します。

失敗したコードは次のとおりです。

return RedirectToAction("IndexComparison", "LifeCycleEffectsResults", model);

注目に値するのは、文字列、整数などがこのコントローラーメソッドへの移行を生き延びていたが、一般的なリストオブジェクトはCメモリリークを連想させるものの影響を受けていたことです。

上記で推奨したように、私が置き換えたコードは次のとおりです。

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

var result = controller.IndexComparison(model);
return result;

現在、すべてが意図したとおりに機能しています。先導してくれてありがとう。


3

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

パラメータが必要な場合、アクション "MethodNameFromControllerB_ToCall"をどのように呼び出しますか?たとえば、MethodNameFromControllerB_ToCall(int somenum、string sometext)?
Patee Gutee、2018

3

古いことは知っていますが、次のことができます。

  • サービス層を作成する
  • そこにメソッドを移動
  • 両方のコントローラーでメソッドを呼び出す

2

問題が電話である場合。このメソッドを使用して呼び出すことができます。

yourController obj= new yourController();

obj.yourAction();

1
うん!代わりにアクションの結果を期待している場合はどうなりますか? var res = new ControllerB().SetUpTimer(new TimeSpan(23, 20, 00));
DirtyBit 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.