ASP.NET Core 2.0中Autofac上下文绑定失效问题求助
I’ve run into this exact issue when migrating from ASP.NET MVC 5/Web API 2 to Core 2.0—let’s break down why your configuration isn’t working and how to fix it.
Why Your Current Setup Fails
There are two critical issues here:
ASP.NET Core’s Default Controller Activation: Unlike older ASP.NET frameworks, Core 2.0 doesn’t use the DI container to activate controllers by default. It creates controllers directly, so your
WithParameterconfigurations on controller registrations are completely ignored. AllISenderdependencies pull the defaultDefaultSenderbecause that’s what the container resolves when the framework requests a plainISender.Syntax Error in Registration: Look closely at your
CustomersControllercode—there’s an extra semicolon afterbuilder.RegisterType<CustomersController>();, which breaks the method chain. TheWithParametercall never attaches to the controller registration, so it never takes effect.
Fixes to Get Contextual Binding Working
Step 1: Let Autofac Take Over Controller Activation
First, tell ASP.NET Core to use the DI container for controller activation. In your Startup.cs ConfigureServices method, add .AddControllersAsServices() to your MVC setup:
public IServiceProvider ConfigureServices(IServiceCollection services) { // Enable controller activation via DI services.AddMvc().AddControllersAsServices(); var builder = new ContainerBuilder(); // Import Core services into Autofac builder.Populate(services); // Your service registrations go here... }
Step 2: Fix the Syntax Error
Remove the extra semicolon in your CustomersController registration:
// Before (broken) builder.RegisterType<CustomersController>(); .WithParameter(...) // After (fixed) builder.RegisterType<CustomersController>() .WithParameter( new ResolvedParameter( (pi, ctx) => pi.ParameterType == typeof(ISender), (pi, ctx) => ctx.Resolve<EmailNotifier>())) .InstancePerLifetimeScope();
Step 3: Use a More Reliable Contextual Binding Approach (Optional but Recommended)
While fixing the above may get your original setup working, using keyed services is a cleaner, more maintainable approach for contextual binding in Autofac:
Register ISender Implementations as Keyed Services
builder.RegisterType<PostalServiceSender>() .Keyed<ISender>("shipping-strategy") .InstancePerLifetimeScope(); builder.RegisterType<EmailNotifier>() .Keyed<ISender>("notification-strategy") .InstancePerLifetimeScope(); // Keep the default ISender registration builder.RegisterType<DefaultSender>() .As<ISender>() .InstancePerLifetimeScope();
Bind Keyed Services to Controllers
You can either use WithParameter with a keyed resolved parameter:
builder.RegisterType<ShippingController>() .WithParameter(ResolvedParameter.ForKeyed<ISender>("shipping-strategy")) .InstancePerLifetimeScope(); builder.RegisterType<CustomersController>() .WithParameter(ResolvedParameter.ForKeyed<ISender>("notification-strategy")) .InstancePerLifetimeScope();
Or use attribute-based filtering directly in your controller constructors (even cleaner):
public class ShippingController : Controller { private readonly ISender _shippingStrategy; public ShippingController([KeyFilter("shipping-strategy")] ISender shippingStrategy) { _shippingStrategy = shippingStrategy; } } public class CustomersController : Controller { private readonly ISender _notificationStrategy; public CustomersController([KeyFilter("notification-strategy")] ISender notificationStrategy) { _notificationStrategy = notificationStrategy; } }
With the attribute approach, you don’t need WithParameter calls on controller registrations—Autofac automatically resolves the correct keyed service based on the [KeyFilter] attribute.
Final Notes
Ensure your ConfigureServices method returns an IServiceProvider to integrate Autofac with ASP.NET Core’s DI system:
var container = builder.Build(); return new AutofacServiceProvider(container);
After these changes, ShippingController will get PostalServiceSender, CustomersController gets EmailNotifier, and all other ISender dependencies will fall back to DefaultSender as expected.
内容的提问来源于stack exchange,提问作者anton.a.popov

