Каков хороший подход для проверки HTTP-запроса в. NET Core 3.1 API? - PullRequest
0 голосов
/ 13 апреля 2020

Я новичок в создании API. Мой проект содержит три типичных уровня: контроллеры, службы, отвечающие за бизнес-логику c, и репозитории, которые обращаются к данным. Каждый запрос, поступающий на мои контроллеры, должен пройти go через некоторый процесс проверки перед выполнением определенного действия c. Для примера, пожалуйста, проверьте код ниже:

[HttpPost]
public async Task<ActionResult<TicketDTO>> CreateTicketAsync([FromBody] CreateTicketDTO ticket)
{
    try
    {
        if (ticket.Events == null)
        {
            return BadRequest(new {Message = _localizer["LackOfEventsErrorMessage"].Value});
        }

        var user = await _userService.GetUserByIdAsync(ticket.UserId);

        if (user == null)
        {
            return NotFound(new { Message = _localizer["UserNotFoundErrorMessage", ticket.UserId].Value });
        }

        var invalidTicket = await _ticketService.CheckHasUserPlayedAnyOfGamesBeforeAsync(ticket);

        if (invalidTicket)
        {
            return BadRequest(new { Message = _localizer["EventsRepeatedByUserErrorMessage"].Value });
        }

        var createdTicket = await _ticketService.AddTicketAsync(ticket);

        if (createdTicket == null)
        {
            return BadRequest(new { Message = _localizer["TicketNotCreatedErrorMessage"].Value });
        }

        return CreatedAtAction(nameof(GetTicketById), new {ticketId = createdTicket.TicketId}, createdTicket);
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError,
            new
            {
                Message = ex.InnerException != null
                    ? $"{ex.Message} {ex.InnerException.Message}"
                    : ex.Message
            });
    }
}

Это один из моих методов контроллера. Прежде чем билет сохраняется в базе данных, он должен пройти несколько проверок. Владелец билета должен существовать, если нет, то я возвращаюсь, пользователь не найден и т. Д. c. Проблема в том, что мне не очень нравится такой способ проверки запросов. Метод грязный и не очень читабельный. Я хотел бы знать, что является хорошим подходом для проверки запросов и правильно реагировать, если что-то пошло не так (например, вернуть «UserNotFoundErrorMessage», если в базе данных нет пользователя, и т. Д. c. Один блок перехвата не решает мою проблему) Я тоже не хотел бы, чтобы там было несколько блоков catch, это также грязно, я думаю. Я ошибаюсь?) Интересно, нарушает ли прикрепленный фрагмент некоторые правила чистого кода или нет? Как должен выглядеть код? Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 13 апреля 2020

Как уже отмечали другие, это не выглядит наполовину плохо.

Я могу вам сказать, что у нас есть фрагменты кода, которые в 10 раз больше этого размера. Но это похоже на небольшую часть по сравнению с некоторыми модулями, которые я видел в кодовой базе моей компании.

При этом вы можете переместить немного больше логики c от контроллера и на другие уровни. Например, при получении пользователя по его идентификатору вы также можете выбросить не найденное исключение из вашего класса обслуживания, если пользователя с таким идентификатором не существует. теперь вы загрузили все в контроллер, хотя кажется, что это больше обеспечивает безопасность службы.

Еще одна вещь, которую вы можете сделать, это, возможно, использовать промежуточное ПО:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1

Вы можете создать конвейеры проверки для своего ответа.

Я также пытался работать с шаблоном проверки. В этом случае я бы создал несколько правил для проверок и применил эти правила к вещам для проверки. Затем у меня был объект-валидатор, который принимал бы все правила и выводил соответствующий вывод. Это улучшило чистоту кода и его повторное использование, однако добавило некоторой сложности, и в итоге я его не использовал. Он отличался от остальной кодовой базы и, следовательно, был чужд коллегам, и поэтому у меня были веские аргументы, чтобы не использовать его.

0 голосов
/ 13 апреля 2020

Все эти логи c должны быть перетасованы в ваш бизнес-уровень, то есть в ваши услуги. Таким образом, методы обслуживания должны возвращать класс «result», который, по сути, является просто способом отправки нескольких битов информации в качестве возвращаемого значения, т. Е. Состояния успеха / неудачи, ошибок, если таковые имеются, фактического результата в случае запрос или что-то, et c. Затем вы можете просто включить ошибку и ответить соответствующим образом.

Что касается перехватов go, особенно основного, который просто возвращает 500, используйте глобальный обработчик исключений. Позвольте ошибке всплыть из действия и положитесь на глобальный обработчик, чтобы вернуть соответствующий ответ.

...