C# MVC 4 Web Api 控制器没有默认构造函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17462175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:32:11  来源:igfitidea点击:

MVC 4 Web Api Controller does not have a default constructor?

c#asp.net-mvc-4asp.net-web-apiinversion-of-controlninject

提问by Komengem

Here is the trace:

这是跟踪:

<Error>
   <Message>An error has occurred.</Message>

   <ExceptionMessage>
      Type 'ProjectName.Web.Api.Controllers.ContinentsController' does not have a default constructor
   </ExceptionMessage>

   <ExceptionType>System.ArgumentException</ExceptionType>

   <StackTrace>
      at System.Linq.Expressions.Expression.New(Type type)

      at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)

      at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)

      at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
   </StackTrace>
</Error>

I find this weird as public class UsersController : ApiController { ... }is working just fine. I have compared the 2 controllers, all the settings and structures are similar.

我觉得这很奇怪,因为public class UsersController : ApiController { ... }它工作得很好。我比较了 2 个控制器,所有设置和结构都相似。

I am using Ninjectand i have my system setup similar to Jamie KurtzAsp.Net Mvc 4 and the Web Api: Building a REST Service from Start to Finish.

我正在使用Ninject并且我的系统设置类似于Jamie KurtzAsp.Net Mvc 4 和 Web Api: Building a REST Service from Start to Finish

From the stack trace, is anyone able to spot the problem and how to solve it? Thanks!

从堆栈跟踪中,是否有人能够发现问题以及如何解决?谢谢!

As Requested.

按照要求。

ContinentsController

大陆控制器

[LoggingNHibernateSession]
public class ContinentsController : ApiController
{
    private readonly ISession _session;
    private readonly IContinentMapper _continentMapper;
    private readonly IHttpContinentFetcher _httpContinentFetcher;
    private readonly IDateTime _dateTime;

    public ContinentsController(ISession session, IContinentMapper continentMapper, IHttpContinentFetcher continentFetcher, IDateTime dateTime)
    {
        _session = session;
        _continentMapper = continentMapper;
        _httpContinentFetcher = continentFetcher;
        _dateTime = dateTime;
    }

    public IEnumerable<Continent> Get()
    {
        var continents = _session
            .Query<Data.Model.Continent>()
            .Select(_continentMapper.CreateContinent)
            .ToList();

        return continents;
    }

    public Continent Get(long id)
    {
        var modelContinent = _httpContinentFetcher.GetContinent(id);
        var continent = _continentMapper.CreateContinent(modelContinent);

            return continent;
        }
  }

UsersController: Works just fine.

UsersController:工作得很好。

    public class UsersController : ApiController
    {
        private readonly ISession _session;
        private readonly IUserManager _userManager;
        private readonly IUserMapper _userMapper;
        private readonly IHttpUserFetcher _userFetcher;

        public UsersController(
            IUserManager userManager,
            IUserMapper userMapper,
            IHttpUserFetcher userFetcher,
            ISession session)
        {
            _userManager = userManager;
            _userMapper = userMapper;
            _userFetcher = userFetcher;
            _session = session;
        }

        [Queryable]
        public IQueryable<Data.Model.User> Get()
        {
            return _session.Query<Data.Model.User>();
        }

        [LoggingNHibernateSession]
        public User Get(Guid id)
        {
            var user = _userFetcher.GetUser(id);
            return _userMapper.CreateUser(user);
        }
    }

I am using NinjectWebCommon.csand in it, i have this and a few other default methods.:

我正在使用NinjectWebCommon.cs它,我有这个和其他一些默认方法。:

        private static void RegisterServices(IKernel kernel)
        {
            var containerConfigurator = new NinjectConfigurator();
            containerConfigurator.Configure(kernel);

            GlobalConfiguration.Configuration.MessageHandlers.Add(kernel.Get<BasicAuthenticationMessageHandler>());
        }

Then i have NinjectConfigurator.cs:

然后我有NinjectConfigurator.cs

public class NinjectConfigurator
{
    ......
    private void AddBindings(IKernel container)
        {
            .....
            container.Bind<IDateTime>().To<DateTimeAdapter>();
            container.Bind<IDatabaseValueParser>().To<DatabaseValueParser>();

            //HttpFetchers
            container.Bind<IHttpUserFetcher>().To<HttpUserFetcher>();
            container.Bind<IHttpContinentFetcher>().To<HttpContinentFetcher>();                                

            //TypeMappers
            container.Bind<IUserManager>().To<UserManager>();
            container.Bind<IMembershipInfoProvider>().To<MembershipAdapter>();
            container.Bind<IUserMapper>().To<UserMapper>();
            container.Bind<IContinentMapper>().To<ContinentMapper>();    
            .........
        }
     .......
}

Both NinjectWebCommon.csand NinjectConfigurator.csare located in the App_Startfolder.

这两个NinjectWebCommon.csNinjectConfigurator.cs位于在App_Start文件夹中。

container.Bind<ISession>().ToMethod(CreateSession);is NHibernate. It is within NinjectConfigurator.csinside private void ConfigureNHibernate(IKernel container) { ... }

container.Bind<ISession>().ToMethod(CreateSession);NHibernate。它在NinjectConfigurator.cs里面private void ConfigureNHibernate(IKernel container) { ... }

采纳答案by Felipe Oriani

This error is a known error when you do not set the dependency resolver in your application. The Controller Factory could not find a parameterless constructor to create the controller and execute the action method (or verb method?). So, you have to create a dependency resolver class and set it on the initialization of your web app. It will resolve dependencies of your controllers.

当您未在应用程序中设置依赖项解析器时,此错误是一个已知错误。控制器工厂找不到无参数构造函数来创建控制器并执行操作方法(或动词方法?)。因此,您必须创建一个依赖解析器类并在您的 Web 应用程序初始化时设置它。它将解决您的控制器的依赖关系。

Using ninject, you could try something like this:

使用ninject,你可以尝试这样的事情:

using Ninject; 
using Ninject.Syntax; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics.Contracts; 
using System.Web.Http.Dependencies; 

namespace MyApplication.App_Start 
{     
    public class NinjectDependencyScope : IDependencyScope     
    {         
        private IResolutionRoot resolver;         

        internal NinjectDependencyScope(IResolutionRoot resolver)         
        {             
            Contract.Assert(resolver != null);             
            this.resolver = resolver;         
        }         

        public void Dispose()         
        {             
            IDisposable disposable = resolver as IDisposable;             
            if (disposable != null)                 
                disposable.Dispose();             
            resolver = null;         
        }         

        public object GetService(Type serviceType)         
        {             
            if (resolver == null)                 
                throw new ObjectDisposedException("this", "This scope has already been disposed");             

            return resolver.TryGet(serviceType);         
        }   

        public IEnumerable GetServices(Type serviceType)         
        {             
            if (resolver == null)                 
                throw new ObjectDisposedException("this", "This scope has already been disposed");             

            return resolver.GetAll(serviceType);         
        }     
    }     

    public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver     
    {         
        private IKernel kernel;         
        public NinjectDependencyResolver(IKernel kernel)             
            : base(kernel)         
        {             
            this.kernel = kernel;         
        }         

        public IDependencyScope BeginScope()         
        {             
            return new NinjectDependencyScope(kernel.BeginBlock());         
        }     
    } 
}

The NinjectDependencyResolverclass takes a Ninject StandardKernelobject as a constructor argument and this reference is used whenever a dependency scope is pipelined. To make this all work, the NinjectDependencyResolverclass is assigned to the application's global configuration:

所述NinjectDependencyResolver类需要一个Ninject StandardKernel对象作为构造器参数,每当一个依赖范围流水线使用此参考。为了使这一切工作,NinjectDependencyResolver该类被分配给应用程序的全局配置:

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

    // register all your dependencies on the kernel container
    RegisterServices(kernel);

    // register the dependency resolver passing the kernel container
    GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

    return kernel;
}

On your Global.asax.csfile in the end of Application_Start event, call this CreateKernelmethod.

Global.asax.csApplication_Start 事件结束的文件上,调用此CreateKernel方法。

回答by atconway

I also ran into this identical error but from another cause using Ninject. I actually had the dependency resolver and configuration correct. In fact the app was working well until I tried to resolve another new dependency. I had the registration set for it, so I could not figure out what was missing.

我也遇到了这个相同的错误,但使用Ninject. 我实际上有正确的依赖解析器和配置。事实上,该应用程序运行良好,直到我尝试解决另一个新的依赖项。我已经为它设置了注册,所以我无法弄清楚缺少什么。

The issue was I accidentallyresolved the Interface to the sameInterface as opposed to resolving to the proper concrete type. So using an example from the OP I did the following which results in the identical error:

问题是我不小心将接口解析为相同的接口,而不是解析为正确的具体类型。因此,使用 OP 中的一个示例,我执行了以下操作,这导致了相同的错误:

container.Bind<IUserManager>().To<IUserManager>();

Notice resolving to IUserManagerwhich was an oversight but it doeslead to the identical error from the OP. Obviously the fix is to resolve to the proper concrete type.

请注意解决IUserManager这是一个疏忽,但它确实导致来自 OP 的相同错误。显然,解决方法是解决正确的具体类型。

回答by crabCRUSHERclamCOLLECTOR

You need to tell Ninject how to correctly resolve Web API dependencies.

您需要告诉 Ninject 如何正确解析 Web API 依赖项。

You can use Felipe Oriani's answer, but if you like there is a NuGet package called WebApiContrib.IoC.Ninject which will do this for you.

您可以使用 Felipe Oriani 的答案,但如果您喜欢,有一个名为 WebApiContrib.IoC.Ninject 的 NuGet 包可以为您执行此操作。

  1. In Visual Studio Go to: Tools > NuGet Package Manager > Manage NuGet Packages for Solution

  2. Install the WebApiContrib.IoC.Ninjectpackage

  3. Edit: NinjectWebCommon.csand update the CreateKernel()method to include: GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

    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);
    
            //Note: Add the line below:
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }
    
  1. 在 Visual Studio 中,转到:工具 > NuGet 包管理器 > 管理解决方案的 NuGet 包

  2. 安装WebApiContrib.IoC.Ninject

  3. 编辑:NinjectWebCommon.cs并更新CreateKernel()方法以包括: GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

    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);
    
            //Note: Add the line below:
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }
    

回答by Mark Cidade

I had this problem, too, but it just turned out that one of my interfaces weren't actually implemented by any classes (I forgot to add it to the class declaration).

我也有这个问题,但结果是我的一个接口实际上没有被任何类实现(我忘记将它添加到类声明中)。

回答by andrei.ciprian

The accepted answer is from 2014. Since tons of people had this issue, as of 2016 there's a recipe for it.This just adds to the accepted answer.

公认的答案是 2014年的由于很多人都遇到过这个问题,因此到 2016 年就有了解决方法。这只是增加了已接受的答案。

The way I do it is by installing packages Ninject.MVC3and WebApiContrib.IoC.Ninject. A file called NinjectWebCommongets added to your App_Startfolder. You can then use the built-in NinjectResolver.

我这样做的方法是安装软件包Ninject.MVC3WebApiContrib.IoC.Ninject. 一个名为的文件NinjectWebCommon被添加到您的App_Start文件夹中。然后,您可以使用内置的NinjectResolver.

Just add this method:

只需添加此方法:

private static void AddWebApiSupport(StandardKernel kernel)
{
  // Support WebAPI
  GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
  GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), new NinjectWebApiFilterProvider(kernel));
}

and call it before calling RegisterServices.

并在调用之前调用它RegisterServices

回答by Debendra Dash

This is a common problem occurs mainly when you work with Ninject Dependency injection Container. Please follow the steps to resolve this problem.  Make sure you have Installed the following packages.

这是一个常见问题,主要发生在您使用 Ninject 依赖注入容器时。请按照步骤解决此问题。  确保您已安装以下软件包。

Again go for this and Install this- enter image description here

再次执行此操作并安装此- 在此处输入图片说明

Now check the the App_start folder.You will find the following thing(NinjectWebcommon.cs). enter image description here

现在检查 App_start 文件夹。您会发现以下内容(NinjectWebcommon.cs)。 在此处输入图片说明

Now double click and check the following line in CreateKernel() method like this

现在双击并检查 CreateKernel() 方法中的以下行,如下所示

 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);
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

And then Register your dependincy like this

然后像这样注册你的依赖

 private static void RegisterServices(IKernel kernel)
    {

        kernel.Bind<IProductDetails>().To<ProductDetails>().InRequestScope();
    }      

I am sure this will make your solution work.

我相信这将使您的解决方案起作用。

回答by Andrew Day

private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<ICountingKsRepository>().To<CountingKsRepository>();

Make sure the To<> part is a concrete class not an interface, as that will create the same error also!

确保 To<> 部分是具体类而不是接口,因为这也会产生相同的错误!

回答by Jamie M

For me, it was just a matter of adding the Ninject.Web.WebApi.Webhost NuGet package.

对我来说,这只是添加 Ninject.Web.WebApi.Webhost NuGet 包的问题。

For my applications that use both MVC and WebApi2, I have the following packages for Ninject:

对于同时使用 MVC 和 WebApi2 的应用程序,我有以下 Ninject 包:

  • Ninject
  • Ninject.MVC5
  • Ninject.Web.Common
  • Ninject.Web.Common.WebHost
  • Ninject.Web.WebApi
  • Ninject.Web.WebApi.WebHost
  • 宁捷
  • Ninject.MVC5
  • Ninject.Web.Common
  • Ninject.Web.Common.WebHost
  • Ninject.Web.WebApi
  • Ninject.Web.WebApi.WebHost

回答by Scott Fraley

In case any SimpleInjectorusers end up in here...

万一有SimpleInjector用户来到这里......

For me, it was simply that I had forgotten to add SimpleInjectorInitializer.Initialize();to my Application_Start()method.

对我来说,这只是我忘记添加SimpleInjectorInitializer.Initialize();到我的Application_Start()方法中。

I typically create a SimpleInjectorInitializerclass in the App_Startfolder these days, within which I do the container.Verify()and GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);calls; after I've called my GetInitializeContainer()method that's doing all the type registrations, etc.

这些天我通常SimpleInjectorInitializerApp_Start文件夹中创建一个类,在其中执行container.Verify()GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);调用;在我调用完成GetInitializeContainer()所有类型注册等的方法之后。

回答by Mehul Parmar

It was happening with me when I did not mention the interface and class for dependency injection in the web.config file.

当我没有在 web.config 文件中提到依赖注入的接口和类时,它发生在我身上。