Как правильно возвращать ошибки из контроллеров ASP NET MVC 5?

Здравствуйте, пишу веб-приложение с помощью ASP NET MVC 5. В приложении есть как Http, так и WebAPI контроллеры. В процессе написания кода возник вопрос: как правильно обрабатывать ошибки? Рассмотрим пример, есть WebAPI контроллер, который имеет два метода - вернуть список товаров и добавить товар:
[HttpGet]
[Route("api/products")]
public IEnumerable<ProductViewModel> Products() => catalog.Products.Select(p => new ProductViewModel{Name = p.Name, Definition = p.Definition, BrandName = p.Brand.Name});

[HttpPost]
[Route("api/createProduct")]
public void CreateProduct(CreatedProductViewModel product)
{
   catalog.AddProduct(new Product(product.Name, product.Definition));
}

В данном случае catalog - это некоторый компонент бизнес-логики, который отвечает за получение списка товаров и добавление товаров, а Product - класс товара из той же бизнес-логики. Для получения и возврата значений с фронта, также есть два простеньких класса - прослойки ProductViewModel, CreatedProductViewModel, которые просто имеют нужные свойства для передачи в виде json без какой-либо логики:
class ProductViewModel
{
public string Name {get;set;}
public string Definition {get;set;}
public string BrandName {get;set;}
}

Если методы выполнились успешно, то всё ок. Однако, где-то ниже могут произойти ошибки, причём как ошибки бизнес-логики (товар с таким именем существует), так и ошибки соединения с БД, например. Как правильно обработать такие ошики? Если никак не обработать, то будет возвращена ошибка с кодом 500 и с текстом из исключения, однако, я читал, что вроде как нехорошо при ошибках бизнес-логики возвращать.

Какие я рассматривал способы решения проблемы:
1) Не обрабатывать вообще, позволяя исключениям проходить на самый верх и возвращать ошибку 500. Я читал, что ошибки 4хх - ошибки пользователя, а 5хх - ошибки системы, поэтому пользователь в основном должен видеть ошибки 4хх. А тут получается исключения из бизнес-логики, например, некорректное имя, превращаются в ошибку 500. Как-то это криво.
2) Ловить исключения в методах контроллера и как-то их обрабатывать. Тут тоже не всё просто. В POST запросах я еще могу вернуть Ok() или BadRequest(), однако, в GET-запросах, у меня уже есть возвращаемое значение и тогда не понятно как вернуть еще Ok/BadRequest. Можно пилить в каждой такой модели ProductViewModel, CreatedProductViewModel еще и поля
bool IsError{get;set;} 
string ErrorMessage {get;set;}

Но, мне кажется, это не красиво.

Как вы обрабатываете ошибки и что у вас возвращают WebAPI контроллеры и Http контроллеры?
  • Вопрос задан
  • 247 просмотров
Пригласить эксперта
Ответы на вопрос 3
@Free_ze
Эксперт в спорах со школьниками
Рассмотрите еще фильтры, как точку перехвата исключений.

Обычно возвращаемая вебная API-модель выглядит примерно так:
{
    "isSuccess": true,
    "errorCode": 0,
    "errorMessage": null,
    "skip": 0,
    "take": 1,
    "data": {...}
}

Данные в нее заворачиваются (поле data).

Ответ генерируется как в контроллерах (успех или ошибки бизнес-правил), так и из перехваченных исключений фильтрами.
Ответ написан
Ошибки обрабатывать нужно, конечно. У меня в реальном приложении WebAPI есть два момента:

1. Перехват и логирование всех исключений через "class GlobalExceptionHandler : IExceptionHandler" и "class GlobalExceptionLogger : ExceptionLogger".

2. Все явные ошибки (например, если переданы от пользователя некорректные данные или объект не найдён в БД или проблемы с правами доступа) обрабатываются в каждом action-е и если что - выбрасывается исключение, производное от HttpResponseException. Это такой специальный тип исключений, который позволяет вернуть произвольный код ошибки (http status) и текст с описанием проблемы для пользователя.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы