question

Gianni-2021 avatar image
0 Votes"
Gianni-2021 asked ZhiLv-MSFT answered

Use IServiceProvider via DI in filter

Good morning

I have a custom class that implement IExceptionFilter in web api Core projetc (3.1)
I need to inject IServiceProvider in "OnException" method. In Startup class, i register my ExceptionFilter

             services.AddMvc(options =>
             {
                 options.Filters.Add(new MyExceptionFilter());
             });

I have try in startup class to use BuildServiceProvider for inject an IServiceProvider and pass it in my filter constructor, but is a bad way.
How can I do?

Thanks


dotnet-aspnet-core-general
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Exception handling is cover in the Handle errors in ASP.NET Core docs. Filters including exception filters is covered in the Filters in ASP.NET Core docs. The community can provide an approach recommendation if you provide details on how your exception logic is intended to function. How does your IExceptionFilter work?


0 Votes 0 ·

In MyExceptionFilter class, I need to add custom information to the Exception object to send to the client. To do this I need to retrieve them, using DI to give me the strings I need.

Regards

0 Votes 0 ·

Hi @Gianni-2021,

Can you post the related code in the MyExceptionFilter class, or create a simple to reproduce the problem, so that we can clearly understand what you want?

Besides, in asp.net core 3.1 application, after creating custom exception filer, we could use the following code to register it in global level in the ConfigureService method:

     public void ConfigureServices(IServiceCollection services)
     { 
         services.AddControllers(config => config.Filters.Add(typeof(HttpResponseExceptionFilter)));

Or register it on the Action method:

     [TypeFilter(typeof(HttpResponseExceptionFilter))]
     [HttpGet]
     [Route("/Filter")]
     public IActionResult Filter()
     {
         throw new HttpResponseException("Testing custom exception filter.");
     }

Reference:

Exception Handling (3), In ASP.NET Core MVC

Exception Handling (4), In ASP.NET Core Web API

Best regards,
Dillion

0 Votes 0 ·

Hi Dillon

Yes, in my first question, i show how I register my custom filter: options.Filters.Add(new MyExceptionFilter());
My question is how can I inject or pass an IServiceProvider in my "MyExceptionFilter" class in "OnException" method for inject object from DI.
I need to enrich the Message error with the information contained in some object contained in the DI engine

Best regards
Gianni

0 Votes 0 ·

1 Answer

ZhiLv-MSFT avatar image
0 Votes"
ZhiLv-MSFT answered

Hi @Gianni-2021,

My question is how can I inject or pass an IServiceProvider in my "MyExceptionFilter" class in "OnException" method for inject object from DI.

Do you mean you want to call the service in the custom exception filter method? If that is the case, you can refer the following sample code to directly inject the service in the custom exception filter or use the IServiceProvider:

Create a IDataRepository to return the test data:

 public interface IDataRepository
 {
     List<Student> GetStudents();
 }

 public class DataRepository : IDataRepository
 {
     public List<Student> GetStudents()
     {
         return new List<Student>()
         {
             new Student(){ ID=1, LastName="AA"},
             new Student(){ ID=2, LastName="BB"},
             new Student(){ ID=3, LastName="CC"},
         };
     }
 }

The custom exception filter as below:

 public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
 {
     //To call the service, we could use the following methods:
     //directly inject the service
     public IDataRepository dataRepository;
     //via the IServiceProvider.
     public IServiceProvider _provider;
     public int Order { get; } = int.MaxValue - 10;
     public HttpResponseExceptionFilter(IServiceProvider serviceProvider, IDataRepository repository)
     {
         _provider = serviceProvider;
         dataRepository = repository;
     }

     public void OnActionExecuting(ActionExecutingContext context) { }

     public void OnActionExecuted(ActionExecutedContext context)
     { 
         //via the service
         var data = dataRepository.GetStudents();
         //via the service provider
         //get the service
         var provider = (IDataRepository)_provider.GetService(typeof(IDataRepository));
         //get the data.
         var data2 = provider.GetStudents();

         if (context.Exception is HttpResponseException exception)
         {
             context.Result = new ObjectResult(exception.Value)
             {
                 StatusCode = exception.Status,
             };
             context.ExceptionHandled = true;
         }
     }
 }

Then, configure the service and the custom exception filter in the ConfigureService method as below:

     public void ConfigureServices(IServiceCollection services)
     {
         services.AddScoped<IDataRepository, DataRepository>();

         services.AddControllers(config => config.Filters.Add(typeof(HttpResponseExceptionFilter)));
         ...
      }

The result as below:

140796-1.gif


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread

Best regards,
Dillion


1.gif (595.2 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.