Не хорошая идея делать блоки Try / Catch / избегать исключений в Web API? - PullRequest
0 голосов
/ 13 ноября 2018

Я прочитал ( здесь ), что не стоит делать блоки Try / Catch и избегать исключений в настройках Web API. Однако, если вы хотите отлавливать и регистрировать ошибки, возникающие в вашем приложении ... не будет ли попытка / уловка лучшим способом решить эту проблему? Вот пример того, что я сделал в своем приложении - мне любопытно, есть ли у кого-нибудь лучший способ. Мой класс ErrorHander сохраняет ошибку в базе данных и отправляет администраторам сообщения об ошибке.

Контроллер

namespace MyApp.Controllers
{
    [Route("api/[controller]")]
    public class AuthController : Controller
    {
        private readonly IAuthRepository _repo;
        private readonly IErrorHandler _errorHandler;

        private AuthController(IAuthRepository repo, IErrorHandler errorHandler) {
            _errorHandler = errorHandler;
        }

        [Authorize]
        [HttpPut("changePassword")]
        public async Task<IActionResult> ChangePassword(
            [FromBody] UserForChangePasswordDto userForChangePasswordDto)
        {
            var userFromRepo = await _repo.Login(userForChangePasswordDto.Username,
                    userForChangePasswordDto.OldPassword, null);

            try
            {
                //logic to update user's password and return updated user

                return Ok(new { tokenString, user });
            }
            catch (Exception ex)
            {
                // emails error to Admin, saves it to DB, then returns HttpStatusCode
                return await _errorHandler.HandleError(
                    HttpStatusCode.InternalServerError, Request, new Error
                {
                    Message = ex.Message,
                    StackTrace = ex.StackTrace,
                    User = userFromRepo != null ? userFromRepo.Username : "Invalid User"
                });
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Если вы хотите перехватывать исключения и делать с ними какие-то общие действия, как, например, в своем примере, то в ASP.NET ваш путь не совсем удачный:)

Когда у вас есть несколько контроллеров и несколько действий внутри каждого контроллера, вы будете иметь много дублирования кода.

ASP.NET Core позволяет вам создать фильтр , в который вы можете поместить всю подобную логику. Это означает, что у вас будет только одно место для обработки необработанных исключений. Вы должны определенно взглянуть на возможности, которые предоставляются с IExceptionFilter

0 голосов
/ 13 ноября 2018

У меня есть несколько рекомендаций:

  1. Избегайте try..catch полностью, когда это возможно.Например, используйте методы типа TryParse, TryCreate и т. Д. Вместо методов, которые генерируют исключения.То же самое относится и к методам *OrDefault LINQ, например, всегда используйте SingleOrDefault, а не Single и т. Д. В принципе, если есть способ вообще исключить исключения, используйте это.

  2. Когда вам нужно обрабатывать исключения, делайте это в своих абстракциях, а не в коде приложения.Например, предположительно, строка //logic to update user's password and return updated user использует ваш IAuthRepository.Метод вашего репо, который вы вызываете, не должен выдавать само исключение.Если код генерирует исключение, перехватите его там и обработайте его там .Затем ваш метод может возвращать что-то вроде логического значения, которое вы можете использовать, чтобы определить, была ли операция успешной или нет, и выполнить соответствующее ветвление.Хотя действительная логика обработки ошибок (администратор электронной почты и т. Д.) Содержится в вашей IErrorHandler абстракции, код вашего приложения все еще работает с этим и зависит от него, что является ненужным знанием предметной области.

  3. Когда вы ловите исключения, ловите определенные исключения.Вы должны точно знать что вы ловите и почему.Поймать что-то столь же общее, как Exception, обычно является признаком ленивого кодирования.Вы можете даже не знать, можно ли вообще вернуть исключение, но вы все еще используете блок try..catch, снижающий производительность.В некоторых сценариях может быть целесообразно перехватить любое возможное исключение, но тогда вы должны всегда повторно генерировать исключение.Глотать каждое возможное исключение - огромное нет-нет.Если вы чувствуете, что не можете повторно вызвать исключение, то вместо этого вы должны нацеливаться на конкретное исключение.

    try
    {
        // do something
    }
    catch (Exception e)
    {
        // log exception
        throw;
    }
    
  4. Отделите обработку ошибок от обработки запросов.Ваше приложение просто должно вернуть ответ на запрос.Это не должно заботиться о таких вещах, как отправка писем вашим админам и тому подобное.Вам нужна какая-то запись о том, что что-то пошло не так, понятно, но для этого достаточно простого ведения журнала и гораздо меньшего веса.Если вы хотите по электронной почте администраторам, вы можете настроить отдельную службу для мониторинга ваших журналов и общих электронных писем, когда это необходимо, что выводит этот процесс из диапазона.

...