简体   繁体   中英

Asp.net Core get instance of Dependency Injection

I am adding a global error handler filter in Startup.cs like this:

services.AddMvc(o =>
{
    o.Filters.Add(new GlobalExceptionFilter());
});

However, I need to pass in my Email Service which is also being injected. How can I retrieve it from these services in the filter?

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly IEmailService _emailService;

    public GlobalExceptionFilter()
    {
    }

    public void OnException(ExceptionContext context)
    {

    }
}

I use to be able to use DependencyResolver Class to do that in MVC5. Is there a way to accomplish this in core? Or is there a way for me to force instantiation of the service in the Startup so I can pass it as part of the constructor?

I tried looking it up in the services and then looking at ImplementationInstance, but its null at this point so I can't grab it from there it appears. Also keep in mind that my EmailService requires a parameter of IOptions<Settings> so that it can get email settings it needs.

You can use constructor injection.

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly IEmailService emailService;
    public GlobalExceptionFilter(IEmailService emailService)
    {
        this.emailService = emailService;
    }
    public void OnException(ExceptionContext context)
    {
       //do something with this.emailService
    }
}

But you have to change the way you are registering the global filter in ConfigureServices method. You should use the Add overload which takes a Type

services.AddMvc(o =>
{
    o.Filters.Add(typeof(GlobalExceptionFilter));
});

Another option is, explicitly resolving the dependency inside the OnException method by calling the GetService method on HttpContext.RequestServices .

using Microsoft.Extensions.DependencyInjection;

public void OnException(ExceptionContext context)
{
    var emailService = context.HttpContext.RequestServices.GetService<IEmailService>();
    // use emailService
} 

But you should be fine with the first approach. Let the framework resolve it for you and inject to your constructor instead of you trying to do it.

I think best practice for a Global Exception Handler is actually to create a custom middleware step for it. From the documentation

Exception filters are good for trapping exceptions that occur within MVC actions, but they're not as flexible as error handling middleware. Prefer middleware for the general case, and use filters only where you need to do error handling differently based on which MVC action was chosen.

Then you register you classes in the ConfigureServices method:

services.AddTransient<IEmailService, EmailService>();

Then in your Configure method, you register your customer global exception handler. You will want this to be the first thing you do in the Configure method so you catch any exceptions following it in other middleware.

app.UseMiddleware<MyGlobalExceptionHandler>();

And any services you registered will be available for your middleware constructor which might look something like this:

public sealed class MyGlobalExceptionHandler
{
    private readonly RequestDelegate _next;
    private readonly IEmailService _emailService;

    public NlogExceptionHandler(
        RequestDelegate next,
        IEmailService emailService)
    {
        _next = next;
        _emailService = emailService;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {

            await _next(context);
        }
        catch (Exception ex)
        {
            try
            {
                _emailService.SendEmail(ex.ToString());
            }
            catch (Exception ex2)
            {
                //Its good practice to have a second catch block for simple logging in case the email fails too
            }

            throw;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM