ASP.NET MVC 4 Ninject MVC 4找不到类型'App.Controller'的默认构造函数

时间:2014-12-19 06:00:29

标签: c# asp.net-mvc-4 mono ninject ioc-container

我在Ubuntu 14.04 LTS(在IDE中运行时使用Mono 3.10.0 mod-mono-server4 / xsp)在Xamarin Studio / monodevelop-opt中设置了一个新的ASP.NET MVC 4应用程序。安装的软件包是:

Install-Package Microsoft.AspNet.Mvc -Version 4.0.40804
  • Microsoft.AspNet.MVC
  • Microsoft.AspNet.Razor
  • Microsoft.AspNet.WebPages
  • Microsoft.Web.Infrastructure

我还必须安装Optimization Framework:

Install-Package Microsoft.AspNet.Web.Optimization

我选择从NuGet实现IoC容器Ninject并安装了以下软件包:

Install-Package Ninject.Mvc4
  • Ninject
  • Ninject.MVC4
  • Ninject.Web.Common.WebHost
  • Ninject.Web.Common

因为我安装了Ninject.Mvc4,它在App_Start中为我创建了一个名为NinjectWebCommon.cs的好文件

这是Create Kernal方法:

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

            RegisterServices (kernel);
            return kernel;
        } catch {
            kernel.Dispose ();
            throw;
        }
    }

以下是注册服务方法:

    private static void RegisterServices (IKernel kernel)
    {
        kernel.Bind<IResourceEntryService> ().To<ResourceEntryService> ();

        var modules = new List<INinjectModule> {
            new ConfigModule (),
            new RepositoryModule (),
            new LoggingModule ()
        };

        kernel.Load (modules);
    }

资源输入服务和界面:

public interface IResourceEntryService
{
    IEnumerable<ResourceEntry> GetResourceEntries ();

    IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture);
}

public class ResourceEntryService : IResourceEntryService
{
    IResourceEntryRepository _resourceEntryRepository;

    public ResourceEntryService (IResourceEntryRepository resourceEntryRepository)
    {
        _resourceEntryRepository = resourceEntryRepository;
    }

    #region IResourceEntryService implementation

    public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntries ()
    {
        IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntries ();
        return resourceEntries;
    }

    public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture)
    {
        IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntriesByNameAndCulture (name, culture);
        return resourceEntries;
    }

    #endregion
}

资源输入控制器将新模型对象传递到视图中:

public class ResourceEntryController : Controller
{
    IResourceEntryService _resourceEntryService;

    public ResourceEntryController (IResourceEntryService resourceEntryService)
    {
        _resourceEntryService = resourceEntryService;
    }

    public ActionResult Index ()
    {
        ResourceEntryViewModel viewModel = new ResourceEntryViewModel ();

        return View (viewModel);
    }
}

这是我的〜/ Views / ResourceEntry / Index.cshtml文件:

@model App.Web.UI.ViewModels.ResourceEntryViewModel

<h1>Resource Page</h1>

所以现在一切看起来都好吗?错了!当我尝试查看该页面时收到以下错误消息。

System.MissingMethodException
Default constructor not found for type App.Web.UI.Controllers.ResourceEntryController

at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00094] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:326 
at System.Activator.CreateInstance (System.Type type) [0x00000] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:222 
at System.Web.Mvc.DefaultControllerFactory+DefaultControllerActivator.Create (System.Web.Routing.RequestContext requestContext, System.Type controllerType) [0x00000] in <filename unknown>:0 

Version Information: 3.10.0 (tarball Sat Oct 4 16:28:24 UTC 2014); ASP.NET Version: 4.0.30319.17020
Powered by Mono

任何人都有任何想法如何设置在单声道堆栈上运行的MVC 4应用程序的Ninject。

我有一个很好的谷歌和堆栈,并且无法真正找到明确的答案。一切都链接到Web API,我对Web API并不感兴趣,因为我将使用ServiceStack。

我只是希望这个Web应用程序能够运行。有人有什么建议吗?

更新:2014年12月20日

在Windows下运行但不是Ubuntu

我创建了一个简单的应用程序,可以在这里找到:

Sample Application

任何想法?

2014年12月21日更新

我尝试过另一种IoC容器实现。

同样的事情发生了,我想这可能是Mono MVC 4 Thing。仍然不知道为什么。

2014年12月22日更新

看起来App_Start在启动时不会被调用。

我在Console.WriteLineCreateKernel中做了RegisterServices,没有打印出来。

我可以通过在Global.ascx.cs文件中配置Container来使SimpleInjector工作。如果它在App_Start中初始化并且顶部有以下行,它将无法工作。

[assembly: WebActivator.PostApplicationStartMethod (typeof(App.Web.UI.App_Start.SimpleInjectorInitializer), "Initialize")]

想知道使用Mono的WebActivator是否存在问题。

1 个答案:

答案 0 :(得分:1)

查看堆栈跟踪,我可以在底部看到DefaultControllerFactory,它将在内部实例化控制器实例,如:

return Activator.CreateInstance(YourControllerType);

这个调用会变得脾气暴躁,因为你的控制器没有无参数构造函数,你没有为它找到一个参数值列表来找到一个合适的构造函数来使用...因此异常。 此外,您不希望提供参数列表,这些参数列表不灵活且无法实现IoC的目的,您希望IoC内核改为创建实例。

现在,我没有使用Ninject的经验,所以可能有更多的“Ninjecty”方式(如果你知道那是什么请加到这个:)但你需要创建自己的DefaultControllerFactory,它可以确定类型并使用Ninject创建它。 像这样:

// NOTE: Something like this, not exactly, I've not used Ninject!

public class YourControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var type = GetControllerType(requestContext, controllerName);

        return kernel.Get(type);
    }
}

在Global.asax中注册:

ControllerBuilder.Current.SetControllerFactory(new YourControllerFactory());

现在您可以控制实例化过程了!