Как сохранить глобально выловленные исключения в базе данных - PullRequest
0 голосов
/ 20 декабря 2018

Я создаю веб-приложение, в котором у меня будет много контроллеров с соответствующими им методами действий.

Я хочу сохранить каждое исключение в базе данных, и по этой причине я создал ExceptionService (DbContext - это

скажем, что это общая форма моих контроллеров:

[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
    private readonly UserManager userManager;
    private readonly IExceptionService exceptionService;

    public UserController(UserManager userManager, IExceptionService exceptionService)
    {
        this.userManager = userManager;
        this.exceptionService = exceptionService;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] User user)
    {

        try
        {
            //some code
        }
        catch (Exception e)
        {
            exceptionService.Save(e);
            //some code
        }
    }
}

Чтобы избежать такого количества блоков try-catch, я решил создать фильтр, который будет выглядетьнапример:

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    private readonly IExceptionService exceptionService;

    public ApiExceptionFilterAttribute(IExceptionService exceptionService)
    {
        this.exceptionService = exceptionService;
    }

    public override void OnException(ExceptionContext context)
    {
        Exception e = context.Exception;
        exceptionService.Save(e);

        //some code
    }
}

Код в методе ConfigureServices в StartUp.cs выглядит следующим образом (часть кода удалена для простоты):

services
    .AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
    .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

services
   .AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));

services.AddScoped<UserManager>();
services.AddScoped<SignInManager>();


services.AddScoped<IExceptionService, ExceptionService>();


services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();

Класс ConfgureMvcOptions выглядит следующим образом:

public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
    private readonly IExceptionService exceptionService;

    public ConfigureMvcOptions(IExceptionService exceptionService)
    {
        this.exceptionService = exceptionService;
    }

    public void Configure(MvcOptions options)
    {
        options.Filters.Add(new ApiExceptionFilterAttribute(exceptionService));
    }
}

Когда я запускаю это приложение, я получаю следующую ошибку:

System.InvalidOperationException: 'Cannot consume scoped service 'SmartWay.Services.IExceptionService' from singleton 'Microsoft.Extensions.Options.IConfigureOptions`1[Microsoft.AspNetCore.Mvc.MvcOptions]'.'

Если я изменю время жизни IExceptionServcise на переходное, чем я должен сделать это для Dbcontext, то для DbContextOptions ... Кажется,что это не правильно ..

Итак, как я могу решить эту проблему?

1 Ответ

0 голосов
/ 21 декабря 2018

Для разрешения службы с единичным сервисом попробуйте _serviceProvider.CreateScope.

Выполните следующие действия:

  1. ExceptionService

    public interface IExceptionService
    {
        void Save(Exception ex);
    }
    
    public class ExceptionService : IExceptionService
    {
        private readonly IServiceProvider _serviceProvider;
        public ExceptionService(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        public void Save(Exception ex)
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var _context = scope.ServiceProvider.GetRequiredService<MVCProContext>();
                _context.Add(new Book() { Title = ex.Message });
                _context.SaveChanges();
            }
        }
    }
    
  2. Startup.cs

    services.AddSingleton<IExceptionService, ExceptionService>();
    services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...