37

我刚刚安装了 mvc4 rc 更新,我正在尝试构建一个 api 应用程序,但运气不佳。

我正在使用 ninject 但无法加载我的控制器。我不断收到错误

类型 'Api.Controllers.ConsumerController' 没有默认构造函数

我对 mvc 和使用注入非常陌生,所以请多多包涵。

我没有对通过 nuget 创建的默认绑定做任何特别的事情

 public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    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)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }        
}

我的控制器看起来像

   private readonly IConsumerRepository _repository;

    public ConsumerController(IConsumerRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public IQueryable<Consumer> Get(Guid id)
    {
        return _repository.Get(id).AsQueryable();
    }

我需要做什么才能让 api 控制器与 ninject 一起工作?

对不起,如果这是简单的东西

但是,在将 webcommon.cs 更改为此之后,我尝试了您的建议 Michael

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

        RegisterServices(kernel);
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(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)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }

我收到错误时

var kernel = new StandardKernel();

叫做

来自程序集“Ninject.Web.WebApi,版本=3.0.0.0,文化=中性,PublicKeyToken=c7192dc5380945e7”的“Ninject.Web.WebApi.Filter.DefaultFilterProvider”类型中的方法“GetFilters”没有实现。

我错过了什么?

4

11 回答 11

60

我向Brad Wilson询问了这个问题,它在 MVC4 RC 中发生了变化。

GlobalConfiguration.Configuration.ServiceResolver已移至GlobalConfiguration.Configuration.DependencyResolver

使用此实现为您的 Web Api 创建一个 Ninject DependencyResolver: https ://gist.github.com/2417226

NinjectWebCommon.cs 中

// Register Dependencies
RegisterServices(kernel);

// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
于 2012-06-01T17:50:17.870 回答
6

您可以安装 NuGet 包 WebApiContrib.IoC.Ninject 并将以下代码行添加到 NinjectWebCommon.cs

GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
于 2013-10-02T22:27:39.573 回答
6

此通用错误消息

类型 'Api.Controllers.ConsumerController' 没有默认构造函数

如果您不公开您的构造函数,或者由于缺少参数,IoC 容器无法解析依赖项,也会发生这种情况。

至少可以说,该错误消息具有误导性。

于 2012-08-15T10:07:00.030 回答
1

对于在搜索“...没有默认构造函数”时登陆这里的人,寻找一种简单的方法来调试静默失败的配置:

  1. 移除构造函数注入的对象,直到可以调用构造函数
  2. 对于之前注入的每个现在未初始化的对象,使用以下命令调用:

ServiceLocator.Current.GetInstance<[OBJ-TYPE]>()

违规对象将导致带有描述性消息的 ActivationException。你会有事可做。

请记住删除对 ServiceLocator 后修复的调用。IE。这不是在调试之外使用服务定位器反模式的建议。

于 2016-02-24T14:16:54.800 回答
0

当您的 IOC 依赖项设置不正确时,Ninject 似乎没有像通常那样抛出异常。相反,它看起来好像我没有注册 WebAPI 依赖解析器,我当然做了。这是我对这个问题的解决方案,但从我发现它可能是许多不同类型的设置问题。只需重新检查依赖链中的所有内容。希望它可以帮助某人!

控制器:

public class ContestsController : ApiController
{
    //Ninject wouldn't inject this CTOR argument resulting in the error
    public ContestsController(IContestEntryService contestEntryService)
    {

依赖:

public class ContestEntryService : IContestEntryService
{

    public ContestEntryService(IContestsContext contestsContext)
    {

错误的配置:

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

        kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

正确的配置:

    private static void RegisterServices(IKernel kernel)
    {
         kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

         kernel.ReBind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

一般来说,Ninject 非常擅长报告这些类型的错误,所以我真的被抛出了一个循环!

于 2013-09-06T18:17:43.540 回答
0

我也收到了这个错误消息,但事实证明我的一个接口实际上并没有被任何类实现(我忘记将它添加到类声明中)。

于 2015-02-24T18:11:17.757 回答
0

如果任何人仍然有问题,请听出于某种原因 ninject 无法按照我们对 mvc 4 的预期工作。在您的 web api 中,您需要编写此代码

public DefaultController() : base() { }  

这消除了关于没有默认构造函数的错误,然后当您需要从 get 方法获取数据时编写以下代码:

public IEnumerable<YourModelGoesHere> Get() 
{
    return context.YourData;  
} 

请记住,您还必须在此处访问您的 db 类,例如:

DefaultConnection context = new DefaultConnection(); 
于 2014-02-13T00:53:22.690 回答
0

我知道这是一篇旧帖子,但我在某个链接上找到了解决方案,所以在这里分享。希望能帮助到你。

http://weblogs.asp.net/hajan/archive/2013/03/16/quick-tip-how-to-make-ninject-work-with-asp-net-web-api.aspx?CommentPosted=true#评论留言

于 2013-09-27T04:11:03.273 回答
0

只需安装 Ninject.MvcXXX 包,其中 XXX - MVC 版本...

于 2015-01-14T14:08:35.980 回答
0

你用框架注册了容器吗?我更喜欢使用 autofac,这里是一个如何将 autofac 与 API 一起使用的示例。http://alexmg.com/post/2012/03/08/Autofac-ASPNET-Web-API-%28Beta%29-Integration.aspx

此外,Mark Seeman 有一篇关于 DI 的好文章,一般来说使用 WebAPI

http://blog.ploeh.dk/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx

来自普洛:

GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
    t => this.container.Kernel.HasComponent(t) ?
        this.container.Resolve(t) :
        null,
    t => this.container.ResolveAll(t).Cast<object>());

以上必须在 global.asax 中执行

于 2012-06-01T13:34:22.023 回答
0

希望这对其他人有帮助...

我遇到了同样的问题,这与我负责注册负责初始化控制器的程序集的移动类有关。从 Web 移出到框架项目中。

使用 Autofac 但同样适用于其他容器。

正在调用:

builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

当它在 Web 应用程序中时工作正常,但是当移动到框架项目时抛出异常,因为执行程序集不再包含控制器。

而是必须更新为:

builder.RegisterApiControllers(Assembly.GetCallingAssembly());
于 2012-08-20T02:13:25.993 回答