ASP.NET MVC:すべてのリクエストに対してコントローラーが作成されますか?


112

非常に単純な質問:ASP.NETのコントローラーはすべてのHTTP要求に対して作成されますか、それともアプリケーションの起動時に作成され、要求全体で再利用されますか?

コントローラは特定のHTTPリクエストに対してのみ作成されますか?

以前の仮定が正しい場合、それに依存できますか?1つの要求に対してのみ有効になるデータベースコンテキスト(Entity Framework)を作成したいと思います。コントローラのコンストラクタで初期化されたプロパティとしてそれを作成する場合、すべてのリクエストに対してコンテキストの新しいインスタンスが作成されることは許可されますか?


16
コンストラクターにブレークポイントを設定して、何がわかるかを確認してください...
Greg B

10
@Greg B:それが常にそのように動作するかどうかを教えてくれないことを除いて素晴らしいアイデア-状況が変化し、一部のコントローラーがその動作を変更する場合、本当に見つけにくいバグがある...
Rasto

@drastoそれが常にそのように機能するかどうかをどのように確認しますか?アプリケーションへのすべてのリクエストを確認しますか?
Greg B

4
@Todd Smithは、リンクまたは少なくともフルネームを入力してください。ツリーの文字IoCはグーグル化するのが難しい。ありがとうございました。
Rasto

2
@drasto IoC = Inversion of control en.wikipedia.org/wiki/Inversion_of_control
Bala R

回答:


103

コントローラは、リクエストごとにControllerFactory(デフォルトではDefaultControllerFactory)作成されます。

http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultcontrollerfactory.aspx

Html.ActionHtml Helperが別のコントローラーを作成することに注意してください。

短いバージョンは、ControllerActivator.Create(すべての要求に対して)コントローラーを作成するために呼び出されます(これは、DependencyResolverまたはResolverがセットアップされていない場合はActivatorを介して新しいコントローラーを初期化します)。

public IController Create(RequestContext requestContext, Type controllerType) 
{
    try 
    {
        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
    }

長いバージョンはこれです(MvcHandlerのソースからのコードは次のとおりです)。

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    SecurityUtil.ProcessInApplicationTrust(() =>
    {
        IController controller;
        IControllerFactory factory;
        ProcessRequestInit(httpContext, out controller, out factory);

        try
        {
            controller.Execute(RequestContext);
        }
        finally
        {
            factory.ReleaseController(controller);
        }
    });
}

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
    // non-relevant code
    // Instantiate the controller and call Execute
    factory = ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(RequestContext, controllerName);
    if (controller == null)
    {
        throw new InvalidOperationException(
            String.Format(
                CultureInfo.CurrentCulture,
                MvcResources.ControllerBuilder_FactoryReturnedNull,
                factory.GetType(),
                controllerName));
    }
}

コントローラのファクトリコードは次のとおりです。

public virtual IController CreateController(RequestContext requestContext, string controllerName) 
{
    Type controllerType = GetControllerType(requestContext, controllerName);
    IController controller = GetControllerInstance(requestContext, controllerType);
    return controller;
}

これは基本的にこれを呼び出します:

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
{
    return ControllerActivator.Create(requestContext, controllerType);
}

これにより、このメソッドが呼び出されますControllerActivator(このコードは、DependencyResolverにインスタンスを要求するか、Activatorクラスを使用するだけです)。

public IController Create(RequestContext requestContext, Type controllerType) 
{
    try 
    {
        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
    }

これはあまりにも多くの情報に該当する可能性があります...しかし、私はあなたが本当にすべてのリクエストに対して新しいコントローラーを取得することを示したかったのです。



32

コントローラーの空のコンストラクターを作成し、コンストラクターにブレークポイントを配置しました。新しいリクエストがあるたびにヒットしました。したがって、すべてのリクエストに対して作成されたと思います。


3
+1私はあなたが正しいことを願っていますが、「私が試したすべての場合にそれがうまくいった」というよりも、いくつかのより承認された知識を求めています。何らかの理由でそのように動作しない場合があるのは、バグを意味します。
Rasto

6
@drasto:心配する必要はありません。コントローラはリクエストごとにインスタンス化されます。一部のメモリは再利用されますが、コントローラの状態を心配する必要はありません(使用している場合)。期待どおりに初期化されます。ただし、複数のコントローラーがインスタンス化される場合もあります。そして、ビューがコントローラーアクションを呼び出すときです(つまり、Html.RenderAction("action", "controller");
Robert Koritnik

@RobertKoritnik&Bala R、質問があります。アクションメソッドがビューまたはオブジェクトに提供した後、StudentまたはList <Student>のように作成されたオブジェクトはどうなりますか?彼らは処分されますか?そして、新しいリクエストが来たときにこれらのオブジェクトはどうなりますか?
Mahdi Alkhatib 2017

3

特定のコントローラーでアクションが実行されると、コントローラーが作成されます。

すべてのコントローラーがから継承するプロジェクトがありApplicationController、アクションが実行されるたびにApplicationController、その「現在の」コントローラーに関係なく、ブレークポイントが内部でヒットします。

コントローラが次のように作成されると、エージェント(コンテキストとして機能します)を初期化します。

    public IWidgetAgent widgetAgent { get; set; }

    public WidgetController()
    {
        if (widgetAgent == null)
        {
            widgetAgent = new WidgetAgent();
        }

    }

これは明らかに必要なものではありません-呼び出されるたびに単一のインスタンスのみが必要であると述べたように。しかし、毎回何が起こっているのかをチェックし、コンテキストの別のインスタンスが現在存在していないことを確認するための良い場所です。

お役に立てれば。


2

コントローラはリクエストごとに作成されます。魔法はgobal.aspxのルーティングで発生します。マッピングパスは、MVCを作成するコントローラーと、コントローラーで呼び出すアクション、およびそれらに渡すパラメーターを指示します。

http://www.asp.net/mvc/tutorials/asp-net-mvc-routing-overview-vb


引用が必要です -リンクされたドキュメントでサポート情報が見つかりません。ありがとう
Rasto
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.