I'm learning ASP.NET Core and I see that registering an MVC service looks like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.MaxModelValidationErrors = 100;
});
}
My question is, why does the AddMvc
method require options in the form of Action<MvcOptions>
? Why can't I just create an instance of MvcOptions
and pass it to the function?
If you look at the source for AddMvc
, you'll see that it doesn't create an instance of MvcOptions
for you:
public static IMvcBuilder AddMvc(this IServiceCollection services, Action<MvcOptions> setupAction)
{
...
var builder = services.AddMvc();
builder.Services.Configure(setupAction);
return builder;
}
Instead, it uses IServiceCollection.Configure
to hook into the more general Options pattern in ASP.NET Core. Behind the scenes, this adds an instance of IConfigureOptions<MvcOptions>
to the Dependency Injection container, which will end up running your delegate at some point later in time.
It's possible to add multiple instances of IConfigureOptions<MvcOptions>
, which will be run in order of registration. There's also IServiceCollection.PostConfigure
, which registers instances of IPostConfigureOptions<MvcOptions>
- these instances will run after all of the IConfigureOptions<MvcOptions>
instances (docs).
This all offers some flexibility. You can set up a pipeline of delegates for configuring MvcOptions
in a set order, where each configuration step might come from other projects, etc. You could even have your own call to services.Configure<MvcOptions>(...)
before your call to AddMvc
, etc.
When adding the MVC services to DI, it's possible to use either AddMvc
or AddMvcCore
. Internally, AddMvc
calls AddMvcCore
, so we can think of AddMvc
as some kind of extension of AddMvcCore
.
AddMvcCore
adds its own configuration, rather than creating an instance of MvcOptions
itself. It adds a set of IConfigureOptions<MvcOptions>
and IPostConfigureOptions<MvcOptions>
to the Dependency Injection container.
These two interfaces are used to assemble a form of pipeline, where all IConfigureOptions<MvcOptions>
run first (in the order they're added to DI) and all IPostConfigureOptions<MvcOptions>
run second (again, in order). This allows AddMvcCore
to provide some defaults (using IConfigureOptions<MvcOptions>
) and also provides the ability to make changes to MvcOptions
once all other configurations have been applied (using IPostConfigureOptions<MvcOptions>
).
When you call AddMvc
and provide a delegate, said delegate will run after the IConfigureOptions<MvcOptions>
added by AddMvcCore
, which provides the ability to override these defaults within your application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With