Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve o tratamento de erros e exceções em ASP.NET API Web.
HttpResponseException
O que acontece se um controlador de API Web gerar uma exceção não capturada? Por padrão, a maioria das exceções é convertida em uma resposta HTTP com o código de status 500, Erro interno do servidor.
O tipo HttpResponseException é um caso especial. Essa exceção retorna qualquer código de status HTTP especificado no construtor de exceção. Por exemplo, o método a seguir retornará 404, Não Encontrado, se o parâmetro de id não for válido.
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Para obter mais controle sobre a resposta, você também pode construir toda a mensagem de resposta e incluí-la com 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;
}
Filtros de exceção
Você pode personalizar como a API Web lida com exceções escrevendo um filtro de exceção. Um filtro de exceção é executado quando um método do controlador gera qualquer exceção que não seja uma exceção HttpResponseException e não tenha sido tratada. O tipo HttpResponseException é um caso especial, pois foi projetado especificamente para retornar uma resposta HTTP.
Os filtros de exceção implementam a interface System.Web.Http.Filters.IExceptionFilter . A maneira mais simples de escrever um filtro de exceção é derivar da classe System.Web.Http.Filters.ExceptionFilterAttribute e substituir o método OnException .
Observação
Os filtros de exceção na API Web ASP.NET são semelhantes aos de ASP.NET MVC. No entanto, eles são declarados em um namespace separado e funcionam separadamente. Em particular, a classe HandleErrorAttribute usada no MVC não lida com exceções geradas por controladores de API Web.
Aqui está um filtro que converte exceções NotImplementedException em código de status HTTP 501, Não Implementado:
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);
}
}
}
}
A propriedade Response do objeto HttpActionExecutedContext contém a mensagem de resposta HTTP que será enviada ao cliente.
Registrando filtros de exceção
Há várias maneiras de registrar um filtro de exceção da API Web:
- Por ação
- Por controlador
- Globalmente
Para aplicar o filtro a uma ação específica, adicione o filtro como um atributo à ação:
public class ProductsController : ApiController
{
[NotImplExceptionFilter]
public Contact GetContact(int id)
{
throw new NotImplementedException("This method is not implemented");
}
}
Para aplicar o filtro a todas as ações em um controlador, adicione o filtro como um atributo à classe de controlador:
[NotImplExceptionFilter]
public class ProductsController : ApiController
{
// ...
}
Para aplicar o filtro globalmente a todos os controladores de API Web, adicione uma instância do filtro à coleção GlobalConfiguration.Configuration.Filters . Os filtros de exceção nesta coleção se aplicam a qualquer ação do controlador de API Web.
GlobalConfiguration.Configuration.Filters.Add(
new ProductStore.NotImplExceptionFilterAttribute());
Se você usar o modelo de projeto "ASP.NET Aplicativo Web MVC 4" para criar seu projeto, coloque o código de configuração da API Web dentro da WebApiConfig classe, que está localizada na pasta App_Start:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());
// Other configuration code...
}
}
HttpError
O objeto HttpError fornece uma maneira consistente de retornar informações de erro no corpo da resposta. O exemplo a seguir mostra como retornar o código de status HTTP 404 (Não Encontrado) com um HttpError no corpo da resposta.
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 é um método de extensão definido na classe System.Net.Http.HttpRequestMessageExtensions . Internamente, CreateErrorResponse cria uma instância httpError e cria um HttpResponseMessage que contém o HttpError.
Neste exemplo, se o método for bem-sucedido, ele retornará o produto na resposta HTTP. Mas se o produto solicitado não for encontrado, a resposta HTTP conterá um HttpError no corpo da solicitação. A resposta pode ser semelhante à seguinte:
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"
}
Observe que o HttpError foi serializado para JSON neste exemplo. Uma vantagem de usar HttpError é que ele passa pelo mesmo processo de negociação de conteúdo e serialização que qualquer outro modelo de tipo forte.
HttpError e Validação de Modelo
Para validação de modelo, você pode passar o estado do modelo para CreateErrorResponse, para incluir os erros de validação na resposta:
public HttpResponseMessage PostProduct(Product item)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
// Implementation not shown...
}
Este exemplo pode retornar a seguinte resposta:
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."
]
}
}
Para obter mais informações sobre a validação de modelo, consulte Validação de Modelo em ASP.NET API Web.
Usando HttpError com HttpResponseException
Os exemplos anteriores retornam uma mensagem HttpResponseMessage da ação do controlador, mas você também pode usar HttpResponseException para retornar um HttpError. Isso permite que você retorne um modelo fortemente tipado no caso de sucesso normal, enquanto ainda retorna HttpError se houver um erro:
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;
}
}