2013-01-15 12 views
12

NuGet Ninject MVC3エクステンションを使用しており、要求に応じてコントローラに注入することができませんでした。それはMVCがparamaterlessコンストラクタを探しているので、バインドされていないようです。ここでスタックトレースです:Ninject + MVC3がコントローラに注入されていません

[MissingMethodException: No parameterless constructor defined for this object.] 
     System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 
     System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98 
     System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 
     System.Activator.CreateInstance(Type type, Boolean nonPublic) +69 
     System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67 

    [InvalidOperationException: An error occurred when trying to create a controller of type 'MyApp.Presentation.Controllers.SearchController'. Make sure that the controller has a parameterless public constructor.] 
     System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182 
     System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80 
     System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74 
     System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +199 
     System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49 
     System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13 
     System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7 
     System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22 
     System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124 
     System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98 
     System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50 
     System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16 
     System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862676 
     System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184 

と私はに注入しようとしているコントローラ(それが現時点では、基本クラスを取る):

public class SearchController : MainBaseController 
{ 

    private readonly MyApp.Domain.Tutor.TutorSearch TutorSearch; 
    protected static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    [Ninject.Inject] 
    public SearchController(MyApp.Domain.Tutor.TutorSearch tutorSearch) 
    { 
     this.TutorSearch = tutorSearch; 
    } 

    .... (no other constructors) 
} 

そして、私のNinjectWebCommon.csの関連部分:

private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
     kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

     RegisterServices(kernel); 
     return kernel; 
    } 

    /// <summary> 
    /// Load your modules or register your services here! 
    /// </summary> 
    /// <param name="kernel">The kernel.</param> 
    private static void RegisterServices(IKernel kernel) 
    { 
     INinjectModule[] modules = new INinjectModule[] 
     { 
      new Domain.DomainModule() 
     }; 

     kernel.Load(Assembly.GetExecutingAssembly()); 
     kernel.Load(modules); 

     kernel.Bind<MyApp.Domain.Tutor.TutorSearch>().ToSelf(); 

     // *************** 
     var t = kernel.Get<MyApp.Presentation.Controllers.SearchController>(); 
    } 

は最後に、ここにDomainModuleです:

public class DomainModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<Data.Profile.IProfileProvider>().To<Data.Profile.XmlProfileProvider>(); 
     Bind<Data.Subject.ISubjectProvider>().To<Data.Subject.XmlSubjectProvider>(); 
    } 
} 

NinjectWebCommon.csのアスタリスクでマークされている行からわかるように、コントローラを明示的にテストとして構築しようとしました。これは、適切に注入されたXml..Providersを使用して、完全に正常に動作します。

私が見逃したことはありますか?私はNuGet MVC3拡張のフードの下で何が起こっているのか十分に分かっていないので、コントローラのバインディングが失敗しているところが分からない。

何を見なければならないかについての指針は、ありがとうと思います。

+0

Trawをあなたの問題を解決するには、あなたが具体的な実装ではなく、インタフェースを使用している特定の理由がある。??これがどのように見えるかの簡単なスケッチを追加しました –

答えて

17

だから必死の工夫のかなりしばらく、私はようやく私の問題を発見しました。 は、私はMVC4(System.Web.Mvc)のDLLを参照したと4.0.0.0に古いバージョン3.0.0.0の結合をリダイレクトされていませんでした:

<dependentAssembly> 
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> 
    <bindingRedirect oldVersion="1.0.0.0" newVersion="4.0.0.0" /> 
    <bindingRedirect oldVersion="2.0.0.0" newVersion="4.0.0.0" /> 
    <!-- The following line was missing --> 
    <bindingRedirect oldVersion="3.0.0.0" newVersion="4.0.0.0" /> 
    </dependentAssembly> 

は、少なくとも、私はそれがまともなソリューションです願っています。

編集:以下示唆したように、次の行がより簡潔である:

Visual StudioとNugetを使用して
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> 
+0

これは、私が[ここ...](http://stackoverflow.com/questions/18723935)を持っていたのと同様の問題を解決する助けとなりました。 – melkisadek

+7

'bindingRedirect oldVersion = "0.0.0.0-4.0.0.0" newVersion = "4.0.0.0" 'これらの3つのケースを1行でカバーしますか? – neontapir

+0

このファイルはどこにありますか?私は同じ問題を抱えています。 – Doug

1

Traw、特に、インターフェイスよりも具体的な実装を使用している理由はありますか?それは、あなたがリファクタリングし、インターフェースの後ろにすべてを置いてから、インターフェースを具体的な実装にバインドすることになります(そして、私はあなたが何かを得ることに驚いています) 。

// 'imagined' ISearchType interface 
public interface ISearchType 
{ 
    int Id { get; set; } 
    string LastName { get; set; } 
} 

// 'imagined' TutorSearch concrete class 
public class TutorSearch : ISearchType 
{ 
    public int Id { get; set; } 
    public string LastName { get; set; } 
} 

// your revised controller code 
private readonly ISearchType _tutorSearch; 
public SearchController(ISearchType searchType) 
{ 
    _tutorSearch = searchType; 
} 

を、その後、サービス(ninject)のご登録には、あなたが追加したい:あなたを取得する必要

kernel.Bind<ISearchType>().To<TutorSearch>(); 

をここで

はそれがどのように見えるかを簡単にショットですもう少し。また、var t = kernel.Get<...>は実際には何もしません。あなたが何が起こったのか不思議に思っていたからです。

は楽しい...

+0

こんにちはジム。まず、あなたの返事をありがとう。私が具体的な実装を使用している理由は、この段階で私はそれを分解することに慣れていないので、問題のクラスは私が注入したい従属関係を持っているからです。私は、Ninjectが具体的なインプリメンテーションを注入しても問題ないと思っていましたか? 'var t = kernel.Get <...>'の行は、私のデバッガで見るための単なるテストであり、うまくいきました.Ninjectはコントローラを完全に構築しました。それはちょうどウェブ要求ではなかった。 私もインターフェイスを通過しようとし、同じ結果を得ました! – Traw

+0

こんにちはTraw - あなたが期待どおりにすべての仕事を得てうれしい。しかし、私は特定のクラスを注入するのをやめてしまいます(たとえできても)。あなたはどんな利点を得ますか?空のコンストラクタにクラスを作成するだけで、実装を変更することはありません。私のアドバイスは、インターフェースを使ってSTARTを行い、具体的な実装をコード化することです。それは具体的なクラスでコードをリファクタリングするだけでよいので、ベストプラクティスになります。さらに、単体テストでは、提供したコード例に基づいて、それを行うことはできません。 –

+0

でも!インターフェイスに対してコーディングすることのもう1つの利点は、他の開発者に作業を提供し、実装が既存の機能に注入可能であることを知ることができるということです。あなたがこのスレッドから何かを取り除くなら、あなたが再び始まり、インターフェイスから仕上げることを私に約束してください - 喜ばしくてください:)幸運を祈ってください。 –

5

あなたは

インストール・パッケージNinjectを、このコマンドを実行する必要があります。MVC3

(あなたが実行している3によって上のMVCのバージョンを置き換える)

これは

+0

これは多かれ少なかれ私のために働いた。私はNinject.MVC5(Ninject.Web.Mvc)をインストールしたと思ったが、そうではなかった。私はちょうど何らかの理由でNinjectとNinject.Web.Commonを持っていました。 – Marnee

関連する問題