Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описывается обработка ошибок и исключений в веб-API ASP.NET.
HttpResponseException
Что произойдет, если контроллер веб-API выбрасывает необработанное исключение? По умолчанию большинство исключений превратятся в HTTP-ответ с кодом состояния 500, внутренняя ошибка сервера.
Тип HttpResponseException — это особый случай. Это исключение возвращает любой код состояния HTTP, указанный в конструкторе исключений. Например, следующий метод возвращает значение 404, не найдено, если параметр идентификатора недопустим.
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Для получения большего контроля над ответом можно также создать все сообщение ответа и включить его в httpResponseException:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("No product with ID = {0}", id)),
ReasonPhrase = "Product ID Not Found"
};
throw new HttpResponseException(resp);
}
return item;
}
Фильтры исключений
Вы можете настроить способ обработки исключений веб-API, написав фильтр исключений. Фильтр исключений выполняется, когда метод контроллера вызывает любое необработанное исключение, которое не является исключением HttpResponseException. Тип HttpResponseException является особым случаем, так как он предназначен специально для возврата HTTP-ответа.
Фильтры исключений реализуют интерфейс System.Web.Http.Filters.IExceptionFilter . Самый простой способ записи фильтра исключений заключается в том, чтобы получить производный от класса System.Web.Http.Filters.ExceptionFilterAttribute и переопределить метод OnException .
Замечание
Фильтры исключений в веб-API ASP.NET похожи на фильтры в ASP.NET MVC. Однако они объявляются в отдельном пространстве имен и функционируют отдельно. В частности, класс HandleErrorAttribute , используемый в MVC, не обрабатывает исключения, создаваемые контроллерами веб-API.
Ниже приведен фильтр, который преобразует исключения NotImplementedException в код состояния HTTP 501, не реализован:
namespace ProductStore.Filters
{
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
}
}
Свойство Response объекта HttpActionExecutedContext содержит сообщение ОТВЕТА HTTP, которое будет отправлено клиенту.
Регистрация фильтров исключений
Существует несколько способов регистрации фильтра исключений веб-API:
- По действию
- По контроллеру
- Глобально
Чтобы применить фильтр к определенному действию, добавьте фильтр в качестве атрибута в действие:
public class ProductsController : ApiController
{
[NotImplExceptionFilter]
public Contact GetContact(int id)
{
throw new NotImplementedException("This method is not implemented");
}
}
Чтобы применить фильтр ко всем действиям на контроллере, добавьте фильтр в качестве атрибута в класс контроллера:
[NotImplExceptionFilter]
public class ProductsController : ApiController
{
// ...
}
Чтобы глобально применить фильтр ко всем контроллерам веб-API, добавьте экземпляр фильтра в коллекцию GlobalConfiguration.Configuration.Filters . Фильтры исключений в этой коллекции применяются к любому действию контроллера веб-API.
GlobalConfiguration.Configuration.Filters.Add(
new ProductStore.NotImplExceptionFilterAttribute());
Если вы используете шаблон проекта "ASP.NET веб-приложение MVC 4" для создания проекта, поместите код конфигурации веб-API в WebApiConfig класс, расположенный в папке App_Start:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());
// Other configuration code...
}
}
HttpError
Объект HttpError предоставляет согласованный способ возврата сведений об ошибке в тексте ответа. В следующем примере показано, как вернуть код состояния HTTP 404 (Не найден) с httpError в тексте ответа.
public HttpResponseMessage GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var message = string.Format("Product with id = {0} not found", id);
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
else
{
return Request.CreateResponse(HttpStatusCode.OK, item);
}
}
CreateErrorResponse — это метод расширения, определенный в классе System.Net.Http.HttpRequestMessageExtensions . Внутренне, CreateErrorResponse создает экземпляр HttpError, а затем создает HttpResponseMessage, содержащий HttpError.
В этом примере, если метод выполнен успешно, он возвращает продукт в ответе HTTP. Но если запрошенный продукт не найден, http-ответ содержит HttpError в тексте запроса. Ответ может выглядеть следующим образом:
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51
{
"Message": "Product with id = 12 not found"
}
Обратите внимание, что HttpError сериализован в JSON в этом примере. Одним из преимуществ использования HttpError является то, что он проходит через тот же процесс согласования содержимого и сериализации, что и любая другая строго типизированная модель.
Проверка HttpError и проверка модели
Для проверки модели можно передать состояние модели в CreateErrorResponse, чтобы включить ошибки проверки в ответ:
public HttpResponseMessage PostProduct(Product item)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
// Implementation not shown...
}
Следующий ответ может быть получен в этом примере:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 320
{
"Message": "The request is invalid.",
"ModelState": {
"item": [
"Required property 'Name' not found in JSON. Path '', line 1, position 14."
],
"item.Name": [
"The Name field is required."
],
"item.Price": [
"The field Price must be between 0 and 999."
]
}
}
Дополнительные сведения о проверке модели см. в разделе "Проверка модели" в веб-API ASP.NET.
Использование HttpError с HttpResponseException
В предыдущих примерах возвращается сообщение HttpResponseMessage из действия контроллера, но вы также можете использовать HttpResponseException для возврата HttpError. Это позволяет возвращать строго типизированную модель в обычном случае успешного выполнения, но при этом возвращается HttpError , если возникает ошибка:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var message = string.Format("Product with id = {0} not found", id);
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
}
else
{
return item;
}
}