MVC 4的Web API控制器没有默认构造函数? [英] MVC 4 Web Api Controller does not have a default constructor?
问题描述
下面是跟踪:
<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>
我觉得这是不可思议的公共类UsersController:ApiController {...}
工作就好了。我比较了2个控制器,所有的设置和结构是相似的。
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.
我使用 Ninject
和我有我类似杰米·库尔茨
<系统设置href=\"http://www.amazon.ca/gp/product/1430249773/ref=s9_simh_gw_p14_d11_i1?pf_rd_m=A3DWYIK6Y9EEQB&pf_rd_s=center-4&pf_rd_r=18BS0P23TZH1Q8KWS8JK&pf_rd_t=101&pf_rd_p=1375923642&pf_rd_i=915398\">Asp.Net MVC 4和Web API:从开始建立一个REST服务来完成
I am using Ninject
and i have my system setup similar to Jamie Kurtz
Asp.Net Mvc 4 and the 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 :工作得很好。
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);
}
}
我使用 NinjectWebCommon.cs
,并在其中,我有这个和其他一些默认方式:
I am using NinjectWebCommon.cs
and in it, i have this and a few other default methods.:
private static void RegisterServices(IKernel kernel)
{
var containerConfigurator = new NinjectConfigurator();
containerConfigurator.Configure(kernel);
GlobalConfiguration.Configuration.MessageHandlers.Add(kernel.Get<BasicAuthenticationMessageHandler>());
}
然后,我有 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>();
.........
}
.......
}
两者 NinjectWebCommon.cs
和 NinjectConfigurator.cs
位于 App_Start
文件夹中。
container.Bind&LT; ISession的方式&gt;()ToMethod(了createSession);
是 NHibernate的
。它是在 NinjectConfigurator.cs
在私人无效ConfigureNHibernate(容器的iKernel){...}
推荐答案
此错误是一个已知的错误,当你没有设置在您的应用程序依赖解析器。控制器工厂找不到参数的构造函数来创建控制器和执行动作的方法(或动词的方法?)。所以,你必须创建一个依赖解析器类并将它放在你的web应用程序的初始化。这将解决您的控制器的依赖关系。
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.
使用 ninject
,你可以尝试这样的事:
Using ninject
, you could try something like this:
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());
}
}
}
的 NinjectDependencyResolver
类需要一个 Ninject StandardKernel
对象作为构造函数的参数,并使用该参考每当一个依赖范围是流水线。
为了使这一切工作,在 NinjectDependencyResolver
类被分配给应用程序的全局配置:
The NinjectDependencyResolver
class takes a Ninject StandardKernel
object as a constructor argument and this reference is used whenever a dependency scope is pipelined.
To make this all work, the NinjectDependencyResolver
class is assigned to the application's global configuration:
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;
}
在在Application_Start事件后,你的的Global.asax.cs
文件,调用这个 CreateKernel
方法。
On your Global.asax.cs
file in the end of Application_Start event, call this CreateKernel
method.
这篇关于MVC 4的Web API控制器没有默认构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!