2009-08-20 7 views
10

Unityコンテナを使用してコントローラの単体テストを容易にしようとしています。私のコントローラは、リポジトリへのインタフェースを受け入れるコンストラクタを使用します。 global.asaxファイルでは、UnityContainerFactoryをインスタンス化し、それをMVCフレームワークに登録し、リポジトリとその実装を登録します。コントローラーのCTOR Repositoryパラメーターに[Dependency]属性を追加しました。これはすべて正常に動作しているようですが、工場のGetControllerInstance(Type controllerType)が複数回呼び出され、null引き数がcontrollerTypeとして渡されることがあるという点が異なります。ASP.NET MVCとUnity 1.2コンテナの質問

ファクトリへの最初の呼び出しは間違いなく、controllerType "ProductsController"が引数として渡されます。しかし、時々、コントローラは、ビューがコントローラのnull値で表示された後、何回か呼ばれ、なぜその理由がわかりません。コントローラータイプの正しい値が渡されたときに、「コールスタック」が意味をなさないが、ヌルが渡されたときに、なぜ、誰が呼び出しているのかわかりません。何か案は?

例のコードとコールスタックを以下に示します。

コールスタック

TEST.DLL!Test.UnityHelpers.UnityControllerFactory.GetControllerInstance動作します(System.TypeをcontrollerType = {= "Test.Controllers.ProductsController" 名前= "ProductsController" フルネームを})23行のC# Test.DLL!Test._Default.Page_Load(オブジェクト送信者= {ASP.default_aspx}、System.EventArgs e = {System.EventArgs})行18 + 0x1aバイトC#

NULLがcontrollerTypeで渡されたときにコールスタック

Test.DLL!Test.UnityHelpers.UnityControllerFactory.GetControllerInstance(Syst em.Type controllerType = null)の27行のC#

まず私はUnityControllerFactory

public class UnityControllerFactory : DefaultControllerFactory 
{ 
    UnityContainer container; 

    public UnityControllerFactory(UnityContainer container) 
    { 
     this.container = container; 
    } 

    protected override IController GetControllerInstance(Type controllerType) 
    { 
     if (controllerType != null) 
     { 
      return container.Resolve(controllerType) as IController; 
     } 
     else 
     { 
      return null; // I never expect to get here, but I do sometimes, the callstack does not show the caller 
     } 
    } 
} 

次へ]を作成し、私は、コンテナ工場

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 

     // Create Unity Container if needed 
     if (_container == null) 
     { 
      _container = new UnityContainer(); 
     } 

     // Instantiate a new factory 
     IControllerFactory unityControllerFactory = new UnityControllerFactory(_container); 

     // Register it with the MVC framework 
     ControllerBuilder.Current.SetControllerFactory(unityControllerFactory); 

     // Register the SqlProductRepository 
     _container.RegisterType<IProductsRepository, SqlProductRepository> 
      (new ContainerControlledLifetimeManager()); 
    } 

をインスタンス化するために、次のコードをGlobal.asaxファイルを追加しましたアプリに1つのコントローラがあります

public class ProductsController : Controller 
{ 
    public IProductsRepository productsRepository; 

    public ProductsController([Dependency]IProductsRepository productsRepository) 
    { 
     this.productsRepository = productsRepository; 
    } 
} 
+0

この行がnullを返さないことを100%確信していますか?return container.Resolve(controllerType)as IController;それは起こりそうもないようですが、結果の型がIControllerでないか、Resolve呼び出しが失敗した場合、そのキャストは簡単にnullを返します。 –

+0

こんにちはAnderson、コールスタックからわかるように、nullが渡されています。また、デバッガを使用している行で停止していて、キャストの前にnullです。この呼び出しは、その時点でスタック上の唯一の関数です。私も理解していない。 Test.DLL!Test.UnityHelpers.UnityControllerFactory.GetControllerInstance(System.Type controllerType = null)27行目C# – Rick

+0

これは私があなたのスタックで見ていたと思ったものですが、私は自分の仮定を確認して確認したかったのです。 –

答えて

9

これはおそらくファイルあなたのルートのコントローラにはマッピングされません。 (例えば、画像)。これは、カッシーニが私の経験でローカルでデバッグしているときに頻繁に起こります。なぜなら、カッシーニはIISを使ってすべてのリクエストをASP.NET経由でルーティングすることができるからです。これはまた、この要求のスタックにコードが表示されない理由です。 Visual Studioで[My Code Just]オプションをオフにすると、これらのことについてのヒントが得られることがあります。

これが起こる唯一の理由ではありませんが、一般的です。

行うには、適切なものは、基本法は、これらの状況で要求を処理できるようになります。これは通常、単純なファイルリクエストであり、影響はありません。

if (controllerType != null) 
    { 
     return container.Resolve(controllerType) as IController; 
    } 
    else 
    { 
     return base.GetControllerInstance(requestContext, controllerType); 
    } 

それにそれを行うべき:行うには

最も簡単な方法は、このようなゲートそこになります。

リクエストの内容を確認するには、HttpContext.Current.Requestをチェックして、自分のルートに含まれていないファイルを確認することができます。何度もあなたがコントロールしたいことではありませんが、要求の起源が何であるかを知ることができます。

+0

ありがとうございました回答とヒント..... – Rick

+2

私はあなたの提案を取り、HttpContext.Current.Requestを見て、favicon.icoを探していたことに気付きました。それはなぜそれが他のものではなく時々働くのかを説明します。ブラウザの既存のインスタンスが開いていたとき、favicon.icoを検索しようとしなかった。 – Rick

+0

こんにちは、私はお手伝いできることを知って嬉しいです。 –