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 为我指明了正确的方向。