I have created a working example in the Autofac Examples repo.
The problem lies in how the .NET Core assembly loader does NOT just assume things in your bin folder are loadable. You absolutely need to tell .NET Core's assembly loader where to get assemblies that are not directly referenced. That's not an Autofac config thing, that's .NET Core and it's pretty confusing new loader system.
When Autofac.Configuration tries to load the configured type from an assembly that isn't referenced, the .NET Core loader doesn't recognize the assembly and raises an event that you need to handle so it can work. A simple solution as shown in the example:
AssemblyLoadContext.Default.Resolving += (AssemblyLoadContext context, AssemblyName assembly) =>
{
// DISCLAIMER: NO PROMISES THIS IS SECURE. You may or may not want this strategy. It's up to
// you to determine if allowing any assembly in the directory to be loaded is acceptable. This
// is for demo purposes only.
return context.LoadFromAssemblyPath(Path.Combine(Directory.GetCurrentDirectory(), $"{assembly.Name}.dll"));
};
The easiest test you can do from your code: If you do Type.GetType("MyNamespace.MyType, MyAssembly")
and come out with a null
, .NET Core is not finding your type and you need to handle assembly loading.
For more info, you should search for questions/answers on how .NET Core assembly loading works.
UPDATE based on comment thread:
It seems there is some confusion about JSON configuration in combination with assembly scanning style registration of controller registration. There also seems to be some confusion about plugin assembly handling mixed in here. I think the combination of these things makes it appear the answer to the question isn't present, when it actually is... or perhaps that the question being asked isn't clear on what the intent is.
As I read it, there are two things desired:
- Auto-register controllers in the application assembly.
- Register additional controllers in an external plugin assembly.
I may already be off-base in my understanding of the question, but that's how it reads, so that's all I can go on.
First, I'd really recommend avoiding plugins if you can. I get that's a really cool thing and probably a feature your app needs, but as noted in my original answer, plugins and assembly loading are really different than how they are in original .NET framework. However, let's just go with it.
When you do something like services.AddControllers()
as shown in this example that's going to register all the controllers from the application assembly. It's not going to pick up plugins, as you've seen. That example does work for the controllers in the application assembly and is the replacement for the WebAPI 2 RegisterApiControllers()
.
Something to note about .NET Core which may not be apparent is that the whole DI system and web application hosting mechanism has been simplified and normalized. There isn't "special treatment" for controllers the way there was in older Web API or ASP.NET MVC. You don't RegisterType<MyController>().As<IController>()
or anything like that anymore. You just register whatever types you want. So if you're looking for something like RegisterApiControllers()
in Autofac, you're not going to find it. The Autofac ASP.NET Core docs cover a lot of the differences and that can help clarify some of this.
This brings us back to the question about how to register things with configuration. I think the configuration you have is right. I can see maybe you need to not register the controller As
anything; or add the type itself, since, again, there's no common controller interface in .NET Core.
{
"components": [{
"type": "Controllers.UserController, Controllers",
"services": [
{"type": "Common.IController, Common"}
{"type": "Controllers.UserController, Controllers"}
]
}]
}
Which brings us to the exception. You posted the exception you were seeing and I already explained the cause - the assembly loading mechanism for .NET Core is not nearly as simple as it is in classic .NET. I already pointed you to a working plugin example. There is not a specific example for ASP.NET Core because, again, there's no specific support or differences for ASP.NET Core than there is for any .NET Core console app or anything else. It's all one thing. .NET Core == ASP.NET Core == self-hosted .NET Core services. You just need to handle the assembly loading portion of things in your ASP.NET Core app.
That's all there is in the question. There's nothing else mentioned in the question about assembly scanning (which is not configuration and isn't something you can specify via configuration). There's nothing about using MEF (which is the AddApplicationPart()
thing that keeps getting noted in the comment thread).
I'm sorry if this isn't enough to answer what you're trying to accomplish. The question asks how to register a controller via configuration and notes an exception, which I addressed. The comment thread keeps coming back to assembly scanning, which isn't configuration but could be addressed by assembly scanning. The exception notes that an assembly couldn't be found and I explained that assembly loading is complicated and is an orthogonal topic to controller registration and that you should look for more information on .NET Core assembly loading if you need that because it's not something Autofac covers, nor does ASP.NET Core, and there's nothing specific to ASP.NET Core when it comes to assembly loading anyway.
I don't think there's anything else I can provide here, so, again, if that's not enough, I'm sorry.