Estou preocupado com a maneira como retornamos erros ao cliente.
Retornamos o erro imediatamente lançando HttpResponseException quando obtemos um erro:
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)
}
}
Ou acumulamos todos os erros e depois devolvemos ao cliente:
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);
}
Este é apenas um código de amostra, não importa erros de validação ou erro do servidor, apenas gostaria de conhecer as melhores práticas, os prós e os contras de cada abordagem.
c#
rest
asp.net-web-api
cuongle
fonte
fonte
ModelState
.HttpResponseException
classe que tem dois parâmetros mencionados em seu post -HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
ou sejaHttpResponseException(string, HttpStatusCode)
Respostas:
Normalmente, para mim, eu envio de volta um
HttpResponseException
e defino o código de status de acordo com a exceção lançada e, se a exceção for fatal ou não, determinará se o envioHttpResponseException
imediatamente.No final do dia, é uma API que envia respostas e não visualizações, então acho que é bom enviar uma mensagem com o código de exceção e status para o consumidor. No momento, não preciso acumular erros e enviá-los de volta, pois a maioria das exceções geralmente ocorre devido a parâmetros ou chamadas incorretos, etc.
Um exemplo no meu aplicativo é que, às vezes, o cliente solicita dados, mas não há dados disponíveis, então eu ligo um
NoDataAvailableException
e deixo ele borbulhar no aplicativo API da Web, onde, em seguida, no meu filtro personalizado, que o captura enviando de volta um mensagem relevante junto com o código de status correto.Não tenho 100% de certeza sobre qual é a melhor prática para isso, mas isso está funcionando para mim atualmente e é isso que estou fazendo.
Atualização :
Desde que eu respondi a essa pergunta, algumas postagens do blog foram escritas sobre o tópico:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(este possui alguns novos recursos nas compilações noturnas) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Atualização 2
Atualize para o nosso processo de tratamento de erros, temos dois casos:
Para erros gerais como não encontrados ou parâmetros inválidos sendo passados para uma ação, retornamos a
HttpResponseException
para interromper o processamento imediatamente. Além disso, para erros de modelo em nossas ações, entregaremos o dicionário de estado do modelo naRequest.CreateErrorResponse
extensão e o envolveremos em umHttpResponseException
. Adicionar o dicionário de estado do modelo resulta em uma lista dos erros de modelo enviados no corpo da resposta.Para erros que ocorrem em camadas mais altas, erros de servidor, deixamos o balão de exceção no aplicativo API da Web, aqui temos um filtro de exceção global que analisa a exceção, a registra no ELMAH e tenta entender a definição do HTTP correto código de status e uma mensagem de erro amigável relevante como o corpo novamente em a
HttpResponseException
. Para exceções que não esperamos, o cliente receberá o erro padrão do servidor interno 500, mas uma mensagem genérica devido a motivos de segurança.Atualização 3
Recentemente, depois de escolher a API da Web 2, para enviar de volta erros gerais, agora usamos a interface IHttpActionResult , especificamente as classes incorporadas no
System.Web.Http.Results
espaço para nome, como NotFound, BadRequest quando cabem, se não o estendermos, por exemplo um resultado NotFound com uma mensagem de resposta:fonte
A API da Web do ASP.NET 2 realmente o simplificou. Por exemplo, o seguinte código:
retorna o seguinte conteúdo para o navegador quando o item não for encontrado:
Sugestão: Não gere o Erro HTTP 500, a menos que haja um erro catastrófico (por exemplo, Exceção de falha do WCF). Escolha um código de status HTTP apropriado que represente o estado dos seus dados. (Veja o link do apigee abaixo.)
Ligações:
fonte
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
que é a diferença entreCreateResponse
eCreateErrorResponse
using System.Net.Http;
que oCreateResponse()
método de extensão seja exibido.Parece que você está tendo mais problemas com a Validação do que erros / exceções, então vou falar um pouco sobre ambos.
Validação
As ações do controlador geralmente devem usar modelos de entrada nos quais a validação é declarada diretamente no modelo.
Em seguida, você pode usar um
ActionFilter
que envia automaticamente mensagens de validação de volta ao cliente.Para mais informações sobre isso, visite http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Manipulação de erros
É melhor retornar uma mensagem ao cliente que represente a exceção que ocorreu (com código de status relevante).
Fora da caixa, você deve usar
Request.CreateErrorResponse(HttpStatusCode, message)
se desejar especificar uma mensagem. No entanto, isso vincula o código aoRequest
objeto, o que você não precisa fazer.Normalmente, crio meu próprio tipo de exceção "segura" que espero que o cliente saiba como manipular e agrupar todas as outras com um erro genérico de 500.
O uso de um filtro de ação para lidar com as exceções seria assim:
Então você pode registrá-lo globalmente.
Este é o meu tipo de exceção personalizado.
Uma exceção de exemplo que minha API pode lançar.
fonte
var exception = context.Exception as WebException;
que foi um erro de digitação, deveria ter sido #ApiException
Você pode lançar um HttpResponseException
fonte
Para a API da Web 2, meus métodos retornam consistentemente IHttpActionResult para que eu use ...
fonte
System.Net.Http
Se você estiver usando a API da Web 2 do ASP.NET, a maneira mais fácil é usar o método curto ApiController. Isso resultará em um BadRequestResult.
fonte
return BadRequest(ModelState);
você pode usar o ActionFilter personalizado na API da Web para validar o modelo
}
Registre a classe CustomAttribute em webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
fonte
Desenvolvendo a
Manish Jain
resposta (que é destinada à API da Web 2, que simplifica as coisas):1) Use estruturas de validação para responder ao maior número possível de erros de validação. Essas estruturas também podem ser usadas para responder a solicitações provenientes de formulários.
2) A camada de serviço retornará
ValidationResult
s, independentemente da operação ter êxito ou não. Por exemplo:3) O API Controller construirá a resposta com base no resultado da função de serviço
Uma opção é colocar virtualmente todos os parâmetros como opcionais e executar a validação personalizada que retorna uma resposta mais significativa. Além disso, estou cuidando para não permitir que nenhuma exceção ultrapasse os limites do serviço.
fonte
Use o método "InternalServerError" incorporado (disponível no ApiController):
fonte
Apenas para atualizar o estado atual da ASP.NET WebAPI. A interface agora é chamada
IActionResult
e a implementação não mudou muito:fonte
Para os erros em que modelstate.isvalid é falso, geralmente envio o erro conforme ele é gerado pelo código. É fácil de entender para o desenvolvedor que está consumindo meu serviço. Eu geralmente envio o resultado usando o código abaixo.
Isso envia o erro ao cliente no formato abaixo, que é basicamente uma lista de erros:
fonte