Autofac - 确保控制器具有无参公共构造函数

21

我知道这个问题之前已经被问过和回答过了-我现在提问的原因是因为(我认为)我尝试了所有建议的解决方案,但仍然无法解决它。

我有一个ASP.NET Web API 2.0项目。我安装了AutofacAutofac.Mvc5Autofac.WebApi2依赖项。当我尝试调用API控制器时,我会得到以下错误:

在试图创建控制器类型“ MyController”时发生错误。请确保该控制器具有无参公共构造函数。

在我的Global.asax文件中,我调用了IocConfig.Config(),并将其放置在App_Start中:

public static class IocConfig
{
    public static void Config()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<MyLogger>().As<IMyLogger>();

        builder.RegisterApiControllers(Assembly.GetCallingAssembly());
        builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);

        WebApiApplication.Container = builder.Build();

        DependencyResolver.SetResolver(
            new AutofacDependencyResolver(WebApiApplication.Container));
        GlobalConfiguration.Configuration.DependencyResolver =
             new AutofacWebApiDependencyResolver(WebApiApplication.Container);
    }
}

这是MyController的构造函数:

public MyController(IMyLogger logger)

我尝试调用它时,遇到了关于构造函数的特定错误。我错过了什么?


1
这个问题解决了吗?我也遇到了同样的问题。我正在使用Asp.Net Web api2.0。 - WonderHeart
6个回答

25
我也遇到了这个错误,其根本原因是其中一个控制器的依赖项在Autofac中没有正确注册。
InnerException 中包含详细信息(在我的情况下,它是 Autofac.Core.DependencyResolutionException),而 ExceptionMessage 包含了这个依赖项的详细信息。大致如下:
“在特定注册的激活期间发生了错误... 无法解析参数 'XXXX'”

2
问题已解决!内部异常包装了真正的问题,即缺少注册。 - DanielV
顺便说一下: 如果您没有关于哪个参数可能由于构造函数不是公共的而出现问题的线索。在我的情况下,构造函数是内部的。将其切换为公共的,然后一切都按预期工作了。 - LosManos
这指引了我正确的方向。非常好的提示! - Paulito.Bandito

16

请查看这个答案,它可以帮助我为WebApi控制器配置正确的ContainerBuilder()

如果您在寻找解决方案来解决此类错误,首先应检查DependencyResolver配置。

我遇到了同样的问题,问题在于我正在使用Autofac代码示例为MVC控制器而不是API创建ContainerBuilder()对象。

我的代码用于注册两种类型的控制器(MVC和API):

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly()); //Register MVC Controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); //Register WebApi Controllers
builder.RegisterType<Type>().As<IType>();

var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //Set the MVC DependencyResolver
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver((IContainer)container); //Set the WebApi DependencyResolver

我没有想到这是答案,因为我错过了汇编线。你能把它加到你的上方描述中吗? - Bluebaron
如果您正在使用ASP.Net Identity,那么这可能是答案。 - Bluebaron
2
@neustart47 最后一行解决了我的问题,感谢您的帮助。 - Campinho

3

Assembly.GetCallingAssembly()将返回调用程序集,而不是定义类型的程序集。

Assembly.GetCallingAssembly方法
返回调用当前执行方法的方法的程序集。

为了使其正常工作,您应该使用typeof(IocConfig).AssemblyAssembly.GetExecutingAssembly


2
我已经尝试过 Assembly.GetExecutingAssembly,也尝试了您建议的尝试 typeof(IocConfig).Assembly - 仍然出现相同的错误。 - developer82

1
您可能忘记了从WebApiConfig.cs文件中调用配置:

IocConfigurator.ConfigureDependencyInjection(config);

ConfigureDependencyInjection可以像这样:

配置依赖注入可以像这样:

public static void ConfigureDependencyInjection(HttpConfiguration config)
        {

            var builder = new ContainerBuilder();

            // Register your Web API controllers.
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            // OPTIONAL: Register the Autofac filter provider.
            builder.RegisterWebApiFilterProvider(config);

            // OPTIONAL: Register the Autofac model binder provider.
            builder.RegisterWebApiModelBinderProvider();

            // Set the dependency resolver to be Autofac.
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

        }

这也许不是推荐的做法,但在一个遗留项目中它却非常有效。我的限制是我不能改变这个项目最初的设置,所以我无法通过启动文件使其正常工作。谢谢! - Paulito.Bandito

0

我认为你在应用程序启动代码中缺少注册autofac。

请使用以下代码:

protected void Application_Start()
{
    IocConfig.Config();
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
   BundleConfig.RegisterBundles(BundleTable.Bundles);
}

更多细节,请参考此博客http://www.codeproject.com/Articles/808894/IoC-in-ASP-NET-MVC-using-Autofac


正如我在原始问题中所写的:“在我的Global.asax中,我调用了IocConfig.Config(),并将其放置在内部” - 它甚至在配置本身中出现了错误 - 所以它肯定运行。 - developer82
它应该在Application_Start中调用,因为这将在应用程序域的生命周期内仅被调用一次。 - error_handler
它只被调用一次。就像在Application_Start中提到的那样。将代码移动到其自己的方法之外,直接放入Application_Start中仍然无法工作。 - developer82

-1

打开您的ServiceModule文件

在控制器中注册接口和服务名称。

示例如下:

builder.RegisterType().As();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接