2

I am making an injectable service (i.e. added using IServiceCollection.AddSingleton...) which works with a custom global action filter. In other words, I need to add the filter:

services.AddControllers(mvcOptions =>
{
   mvcOptions.Filters.Add<MyActionFilter>();
});

But I also need to register my component:

services.AddSingleton<IMyService, MyService>();

This all works great. However, now I need to package this registration up for re-use in multiple projects. To do this I would like to produce a little helper which can perform all my registration, such as:

services.AddControllers(mvcOptions =>
{
   mvcOptions.AddMyService(services);
});
// or
services.AddMyService();

Basically, the consumer of this registration need not be concerned about the relationship of the action filter and my service -- only that my service can be resolved via dependency injection.

The problem is, the callback in AddControllers gets called after the graph has been built, so adding my service in that context is not helpful. But also I am unable to add my action filter outside of the AddControllers callback scope (as far as I can tell).

Instead of having to author two registration methods my consumers will be required to call, is there a way to accomplish what I am trying to do?

Thanks!

1 Answer 1

7

Option 1:

AddControllers supports being called multiple times, so your IServiceCollection extension could be as simple as this:

services.AddSingleton<IMyService, MyService>();

services.AddControllers(mvcOptions =>
{
    mvcOptions.Filters.Add<MyActionFilter>();
});

Option 2:

If you just want to register the filter and service with the assumption that the consumer calls AddControllers, your IServiceCollection extension method could look like this:

services.AddSingleton<IMyService, MyService>();

services.Configure<MvcOptions>(mvcOptions =>
{
    mvcOptions.Filters.Add<MyActionFilter>();
});

Option 3:

You could create an extension for IMvcBuilder that would allow the consumer to write something like this:

services.AddControllers()
    .AddMyService();

To support this, use the following extension method:

public static class MvcBuilderExtensions
{
    public static IMvcBuilder AddMyService(this IMvcBuilder mvcBuilder)
    {
        mvcBuilder.Services.AddSingleton<IMyService, MyService>();

        mvcBuilder.AddMvcOptions(mvcOptions =>
        {
            mvcOptions.Filters.Add<MyActionFilter>();
        });

        return mvcBuilder;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.