Autofac:设置 Web API 2,我缺少什么
Autofac: setting up with Web API 2, what am I missing
我正在一个独立的 C# 解决方案中测试 Autofac,我想将一个测试管理器注入到家庭控制器中,它的设置如下:
一个非常简单的界面
public interface ITestManager
{
IEnumerable<string> Get();
}
实施者
public class TestManager : ITestManager
{
public IEnumerable<string> Get()
{
return new List<string>
{
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, ",
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ",
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ",
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ",
"voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ",
"occaecat cupidatat non proident, sunt in culpa qui officia ",
"deserunt mollit anim id est laborum."
};
}
}
这将由 TestController 接收
public class TestController : Controller
{
private ITestManager TestManager { get; set; }
public TestController(ITestManager testManager)
{
TestManager = testManager;
}
}
并且依赖是这样设置的
public static class Autofac
{
public static void Register(HttpConfiguration config)
{
// Base set-up
var builder = new ContainerBuilder();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
builder.RegisterWebApiFilterProvider(config);
// Register dependencies
SetUpRegistration(builder);
// Build registration.
var container = builder.Build();
// Set the dependency resolver to be Autofac.
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
private static void SetUpRegistration(ContainerBuilder builder)
{
builder.RegisterType<TestManager>()
.As<ITestManager>()
.InstancePerLifetimeScope();
}
}
从global.asax
内链接
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
IoC.Autofac.Register(GlobalConfiguration.Configuration);
}
运行 这会导致此错误:
Server Error in '/' Application.
No parameterless constructor defined for this object.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless
constructor defined for this object.
我错过了什么?
完整堆栈跟踪:
堆栈跟踪
[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, StackCrawlMark& stackMark) +119
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
System.Activator.CreateInstance(Type type) +11
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55
[InvalidOperationException: An error occurred when trying to create a controller of type 'AutofacWebApi.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +191
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
很简单,我从HomeController中复制了控制器class的信息,是Controller
类型的,不是ApiController
!
所以正确的实现是这样的:
public class TestController : ApiController
{
private ITestManager TestManager { get; set; }
public TestController(ITestManager testManager)
{
TestManager = testManager;
}
// GET: api/Test
public IEnumerable<string> Get()
{
return this.TestManager.Get();
}
}
我使用 builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
来注册控制器,但这仅适用于 API 控制器,而且,因为我的 TestController 是 Controller
类型(这是核心 MVC控制器类型)它没有正确连接。
如果你也想使用(普通的)MVC,你应该使用这个:
builder.RegisterControllers(Assembly.GetExecutingAssembly())
感谢 wal 为我指明了正确的方向。
我正在一个独立的 C# 解决方案中测试 Autofac,我想将一个测试管理器注入到家庭控制器中,它的设置如下:
一个非常简单的界面
public interface ITestManager
{
IEnumerable<string> Get();
}
实施者
public class TestManager : ITestManager
{
public IEnumerable<string> Get()
{
return new List<string>
{
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, ",
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ",
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ",
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in ",
"voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ",
"occaecat cupidatat non proident, sunt in culpa qui officia ",
"deserunt mollit anim id est laborum."
};
}
}
这将由 TestController 接收
public class TestController : Controller
{
private ITestManager TestManager { get; set; }
public TestController(ITestManager testManager)
{
TestManager = testManager;
}
}
并且依赖是这样设置的
public static class Autofac
{
public static void Register(HttpConfiguration config)
{
// Base set-up
var builder = new ContainerBuilder();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
builder.RegisterWebApiFilterProvider(config);
// Register dependencies
SetUpRegistration(builder);
// Build registration.
var container = builder.Build();
// Set the dependency resolver to be Autofac.
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
private static void SetUpRegistration(ContainerBuilder builder)
{
builder.RegisterType<TestManager>()
.As<ITestManager>()
.InstancePerLifetimeScope();
}
}
从global.asax
内链接protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
IoC.Autofac.Register(GlobalConfiguration.Configuration);
}
运行 这会导致此错误:
Server Error in '/' Application.
No parameterless constructor defined for this object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.
我错过了什么?
完整堆栈跟踪:
堆栈跟踪
[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, StackCrawlMark& stackMark) +119
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
System.Activator.CreateInstance(Type type) +11
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55
[InvalidOperationException: An error occurred when trying to create a controller of type 'AutofacWebApi.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +191
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
很简单,我从HomeController中复制了控制器class的信息,是Controller
类型的,不是ApiController
!
所以正确的实现是这样的:
public class TestController : ApiController
{
private ITestManager TestManager { get; set; }
public TestController(ITestManager testManager)
{
TestManager = testManager;
}
// GET: api/Test
public IEnumerable<string> Get()
{
return this.TestManager.Get();
}
}
我使用 builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
来注册控制器,但这仅适用于 API 控制器,而且,因为我的 TestController 是 Controller
类型(这是核心 MVC控制器类型)它没有正确连接。
如果你也想使用(普通的)MVC,你应该使用这个:
builder.RegisterControllers(Assembly.GetExecutingAssembly())
感谢 wal 为我指明了正确的方向。