У меня есть опасения по поводу того, как мы возвращаем ошибки клиенту.
Должны ли мы немедленно возвращать ошибку, выбрасывая HttpResponseException, когда мы получаем ошибку:
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
Или мы накапливаем все ошибки и отправляем обратно клиенту:
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
Это просто пример кода, не имеет значения ни ошибки валидации, ни ошибки сервера, я просто хотел бы узнать лучшие практики, плюсы и минусы каждого подхода.
c#
rest
asp.net-web-api
cuongle
источник
источник
ModelState
.HttpResponseException
класса, который принимает два параметра, упомянутых в вашем посте -HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
то естьHttpResponseException(string, HttpStatusCode)
Ответы:
Для меня я обычно отправляю обратно
HttpResponseException
и устанавливаю код состояния соответственно в зависимости от выданного исключения, и если исключение является фатальным или нет, определит, отправлю ли я егоHttpResponseException
немедленно.В конце концов, это API, который отправляет ответы, а не просмотры, поэтому я думаю, что можно отправлять сообщение с кодом исключения и кодом потребителю. В настоящее время мне не нужно накапливать ошибки и отправлять их обратно, так как большинство исключений обычно связано с неправильными параметрами или вызовами и т. Д.
Примером в моем приложении является то, что иногда клиент запрашивает данные, но нет доступных данных, поэтому я выбрасываю пользовательский
NoDataAvailableException
и отправляю его в приложение Web API, где затем в моем пользовательском фильтре, который фиксирует отправку обратно соответствующее сообщение вместе с правильным кодом статуса.Я не уверен на 100% в том, что лучше для этого делать, но сейчас это работает для меня, поэтому я так и делаю.
Обновление :
С тех пор как я ответил на этот вопрос, на эту тему было написано несколько постов в блоге:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(у этого есть некоторые новые функции в ночных сборках) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Обновление 2
Обновление нашего процесса обработки ошибок, у нас есть два случая:
Для общих ошибок, таких как не найденные или неверные параметры, переданные действию, мы возвращаем a,
HttpResponseException
чтобы немедленно остановить обработку. Кроме того, для ошибок модели в наших действиях мы передадим словарь состояния моделиRequest.CreateErrorResponse
расширению и поместим его вHttpResponseException
. Добавление словаря состояния модели приводит к появлению списка ошибок модели, отправленных в теле ответа.Для ошибок, возникающих на более высоких уровнях, ошибок сервера, мы допускаем всплытие исключения в приложение Web API, здесь у нас есть глобальный фильтр исключений, который просматривает исключение, регистрирует его с помощью ELMAH и пытается найти смысл, устанавливая правильный HTTP код состояния и соответствующее дружеское сообщение об ошибке в качестве тела снова в
HttpResponseException
. За исключением тех случаев, когда мы не ожидаем, что клиент получит внутреннюю ошибку сервера по умолчанию 500, но это общее сообщение по соображениям безопасности.Обновление 3
Недавно, после получения Web API 2, для отправки общих ошибок мы теперь используем интерфейс IHttpActionResult , в частности, встроенные классы для в
System.Web.Http.Results
пространстве имен, такие как NotFound, BadRequest, когда они подходят, если они не расширяют их, например, NotFound результат с ответным сообщением:источник
ASP.NET Web API 2 действительно упростил это. Например, следующий код:
возвращает следующий контент в браузер, когда элемент не найден:
Рекомендация: не выбрасывайте HTTP-ошибку 500, если нет катастрофической ошибки (например, исключение ошибки WCF). Выберите соответствующий код состояния HTTP, который представляет состояние ваших данных. (См. Ссылку на Apigee ниже.)
Ссылки:
источник
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Какова разница междуCreateResponse
иCreateErrorResponse
using System.Net.Http;
дляCreateResponse()
метода расширения, чтобы показать.Похоже, у вас больше проблем с валидацией, чем с ошибками / исключениями, поэтому я немного расскажу об обоих.
Проверка
Действия контроллера, как правило, должны принимать входные модели, где валидация объявляется непосредственно в модели.
Затем вы можете использовать функцию,
ActionFilter
которая автоматически отправляет сообщения проверки клиенту.Для получения дополнительной информации об этом проверьте http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Обработка ошибок
Лучше всего вернуть клиенту сообщение, которое представляет исключение, которое произошло (с соответствующим кодом состояния).
Из коробки вы должны использовать,
Request.CreateErrorResponse(HttpStatusCode, message)
если вы хотите указать сообщение. Однако это связывает код сRequest
объектом, что вам не нужно делать.Я обычно создаю свой собственный тип «безопасного» исключения, которое, как я ожидаю, клиент будет знать, как обрабатывать и оборачивать все остальные с общей ошибкой 500.
Использование фильтра действий для обработки исключений будет выглядеть так:
Тогда вы можете зарегистрировать это глобально.
Это мой пользовательский тип исключения.
Пример исключения, которое может выдать мой API.
источник
var exception = context.Exception as WebException;
что это опечатка, это должно было бытьApiException
Вы можете бросить HttpResponseException
источник
Для Web API 2 мои методы последовательно возвращают IHttpActionResult, поэтому я использую ...
источник
System.Net.Http
Если вы используете ASP.NET Web API 2, самый простой способ - использовать короткий метод ApiController. Это приведет к BadRequestResult.
источник
return BadRequest(ModelState);
вы можете использовать собственный ActionFilter в Web Api для проверки модели
}
Зарегистрируйте класс CustomAttribute в webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
источник
Основываясь на
Manish Jain
ответе (который предназначен для Web API 2, который упрощает вещи):1) Используйте структуры проверки, чтобы ответить как можно больше ошибок проверки. Эти структуры также могут использоваться для ответа на запросы, поступающие из форм.
2) Сервисный уровень будет возвращать
ValidationResult
s независимо от того, успешна операция или нет. Например:3) Контроллер API построит ответ на основе результата сервисной функции
Один из вариантов - поместить практически все параметры в качестве необязательных и выполнить пользовательскую проверку, которая возвращает более значимый ответ. Кроме того, я стараюсь не допустить, чтобы какое-либо исключение выходило за границы обслуживания.
источник
Используйте встроенный метод «InternalServerError» (доступен в ApiController):
источник
Просто чтобы обновить текущее состояние ASP.NET WebAPI. Теперь интерфейс вызывается,
IActionResult
и реализация не сильно изменилась:источник
Для тех ошибок, где modelstate.isvalid имеет значение false, я обычно отправляю ошибку, поскольку она генерируется кодом. Это легко понять разработчику, который использует мой сервис. Я обычно отправляю результат, используя приведенный ниже код.
Это отправляет ошибку клиенту в следующем формате, который в основном представляет собой список ошибок:
источник