2013-01-15 24 views
12

Tôi đã sử dụng phần mở rộng NuGet Ninject MVC3 và không thể đưa nó vào bộ điều khiển theo yêu cầu. Nó dường như không có ràng buộc, như MVC đang tìm kiếm các constructor paramaterless. Dưới đây là stack trace:Ninject + MVC3 không được đưa vào bộ điều khiển

[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 

Và bộ điều khiển i đang cố gắng để tiêm vào (phải mất một lớp cơ sở tại thời điểm này):

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) 
} 

Và phần liên quan của NinjectWebCommon.cs của tôi:

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>(); 
    } 

Cuối cùng, đây là 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>(); 
    } 
} 

Như bạn có thể thấy trong NinjectWebCommon.cs của tôi tại dòng được đánh dấu sao, tôi đã cố gắng xây dựng bộ điều khiển một cách rõ ràng như một thử nghiệm. Điều này hoạt động hoàn toàn tốt đẹp, với Xml..Providers tiêm đúng cách.

Có điều gì tôi đã bỏ lỡ không? Tôi không biết đủ về những gì diễn ra dưới sự che chở của phần mở rộng NuGet MVC3 và do đó không có ý tưởng tại điểm mà các ràng buộc điều khiển không thành công.

Mọi gợi ý về nội dung cần xem sẽ được đánh giá rất cao, cảm ơn.

+0

Traw, là có một lý do cụ thể mà bạn đang sử dụng triển khai cụ thể chứ không phải giao diện. ?? Tôi đã thêm một bản phác thảo nhanh về cách thức này sẽ trông như thế nào –

Trả lời

17

Vì vậy, sau một thời gian tuyệt vọng, tôi cuối cùng đã tìm thấy sự cố của mình. Tôi đã tham khảo MVC4 (System.Web.Mvc) DLL và đã không được chuyển các ràng buộc của các phiên bản cũ 3.0.0.0 đến 4.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> 

Ít nhất, tôi hy vọng đó là một giải pháp phù hợp.

Edit: theo đề nghị dưới đây, dòng sau là gọn gàng hơn:

<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> 
+0

điều này đã giúp giải quyết một vấn đề tương tự tôi đã gặp [ở đây ...] (http://stackoverflow.com/questions/18723935) – melkisadek

+7

Sẽ không 'bindingRedirect oldVersion = "0.0.0.0-4.0.0.0" newVersion = "4.0.0.0" 'bao gồm ba trường hợp đó trong một dòng? – neontapir

+0

Tôi có thể tìm tệp này ở đâu? Im có cùng một vấn đề. – Doug

1

Traw, có lý do cụ thể nào mà bạn đang sử dụng triển khai cụ thể thay vì Giao diện. ?? Như nó đứng, bạn đang đạt được lợi ích không từ DI'ing lớp thẳng vào (và tôi ngạc nhiên rằng bạn đang nhận được bất cứ điều gì để làm việc) tôi sẽ refactor và đặt tất cả mọi thứ đằng sau một giao diện, sau đó ràng buộc giao diện để thực hiện cụ thể .

Dưới đây là một shot nhanh chóng như thế nào mà có thể xem xét:

// '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; 
} 

sau đó, trong việc đăng ký của bạn của các dịch vụ (Ninject), bạn muốn thêm:

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

Điều đó sẽ giúp bạn có được một xa hơn một chút. Ngoài ra, var t = kernel.Get<...> thực sự không làm gì cả - chỉ trong trường hợp bạn đang tự hỏi về những gì đã xảy ra với 'nó'.

Vui chơi ...

+0

Xin chào Jim. Trước hết, cảm ơn bạn đã trả lời. Lý do tôi đang sử dụng việc thực hiện cụ thể là bởi vì ở giai đoạn này tôi đã không nhận được xung quanh để bao thanh toán nó ra, và lớp học trong câu hỏi có những phụ thuộc tôi muốn tiêm. Tôi đã ấn tượng rằng Ninject sẽ ổn với việc tiêm một sự thực thi cụ thể hay là không phải vậy? Dòng với 'var t = kernel.Get <...>' chỉ đơn giản là một thử nghiệm để tôi xem xét trong trình gỡ rối của tôi, và nó hoạt động tốt - Ninject đã xây dựng bộ điều khiển một cách hoàn hảo. Nó chỉ không theo yêu cầu web. Tôi cũng đã thử truyền một giao diện và nhận được kết quả tương tự! – Traw

+0

Hi Traw - vui vì bạn đã có mọi thứ hoạt động như mong đợi. tuy nhiên, tôi sẽ không khuyến khích tiêm các lớp bê tông qua ninject (ngay cả khi bạn có thể). bạn có được lợi thế gì? bạn cũng chỉ muốn tạo lớp trong trình xây dựng rỗng vì nó sẽ không bao giờ thay đổi việc triển khai. lời khuyên của tôi sẽ là bắt đầu với các giao diện và mã hóa các triển khai cụ thể của bạn dựa vào các giao diện đó. đó sẽ là cách thực hành tốt nhất khi bạn chỉ phải mã refactor trong các lớp cụ thể. Ngoài ra, đối với thử nghiệm đơn vị, không có cách nào bạn có thể làm bất kỳ điều nào dựa trên ví dụ mã mà bạn đã cung cấp. –

+0

cũng !! một ưu điểm khác của việc viết mã chống lại một giao diện là một thực tế rằng bạn có thể làm việc cho các nhà phát triển khác và biết rằng việc triển khai sẽ được tiêm vào chức năng hiện có. nếu bạn lấy bất cứ điều gì từ chủ đề này, xin hãy hứa với tôi rằng bạn sẽ bắt đầu lại và làm việc từ các giao diện -xin vui lòng, xin vui lòng xin vui lòng :) chúc may mắn .. –

5

Sử dụng Visual Studio và NuGet bạn cần phải chạy lệnh này

Install-Package Ninject.MVC3

(thay thế cho 3 tùy thuộc vào phiên bản MVC bạn đang chạy)

này sẽ giải quyết vấn đề của bạn

+0

Điều này ít nhiều hiệu quả đối với tôi. Tôi nghĩ rằng tôi đã cài đặt Ninject.MVC5 (Ninject.Web.Mvc) nhưng không phải vậy. Tôi đã có Ninject và Ninject.Web.Common vì một lý do nào đó. – Marnee

Các vấn đề liên quan