Estou usando o ASP.NET Core para meu novo projeto de API REST depois de usar a API da Web ASP.NET regular por muitos anos. Não vejo uma boa maneira de lidar com exceções na API da Web do ASP.NET Core. Tentei implementar o filtro / atributo de tratamento de exceções:
public class ErrorHandlingFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
HandleExceptionAsync(context);
context.ExceptionHandled = true;
}
private static void HandleExceptionAsync(ExceptionContext context)
{
var exception = context.Exception;
if (exception is MyNotFoundException)
SetExceptionResult(context, exception, HttpStatusCode.NotFound);
else if (exception is MyUnauthorizedException)
SetExceptionResult(context, exception, HttpStatusCode.Unauthorized);
else if (exception is MyException)
SetExceptionResult(context, exception, HttpStatusCode.BadRequest);
else
SetExceptionResult(context, exception, HttpStatusCode.InternalServerError);
}
private static void SetExceptionResult(
ExceptionContext context,
Exception exception,
HttpStatusCode code)
{
context.Result = new JsonResult(new ApiResponse(exception))
{
StatusCode = (int)code
};
}
}
E aqui está o meu registro de filtro de inicialização:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
O problema que eu estava tendo é que, quando ocorre uma exceção no meu, AuthorizationFilter
ele não está sendo tratado ErrorHandlingFilter
. Eu esperava que fosse pego lá, exatamente como funcionava com a antiga API da Web do ASP.NET.
Então, como posso capturar todas as exceções de aplicativos e de filtros de ação?
c#
exception
asp.net-core
Andrei
fonte
fonte
UseExceptionHandler
middleware?UseExceptionHandler
middlewareRespostas:
Tratamento de exceções Middleware
Depois de muitas experiências com diferentes abordagens de manipulação de exceções, acabei usando o middleware. Funcionou melhor para o meu aplicativo ASP.NET Core Web API. Ele lida com exceções de aplicativos, além de filtros de ação, e eu tenho controle total sobre o tratamento de exceções e a resposta HTTP. Aqui está minha exceção ao lidar com o middleware:
Registre-o antes do MVC na
Startup
classe:Você pode adicionar rastreamento de pilha, nome do tipo de exceção, códigos de erro ou qualquer coisa que desejar. Muito flexível. Aqui está um exemplo de resposta de exceção:
Considere injetar
IOptions<MvcJsonOptions>
oInvoke
método para usá-lo quando serializar o objeto de resposta para utilizar as configurações de serialização do ASP.NET MVCJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
para obter melhor consistência de serialização em todos os pontos de extremidade.Abordagem 2
Existe outra API não óbvia chamada
UseExceptionHandler
que funciona "ok" para cenários simples:Essa não é uma maneira muito óbvia, mas fácil de configurar o tratamento de exceções. No entanto, ainda prefiro a abordagem de middleware em vez de obter mais controle com capacidade de injetar as dependências necessárias.
fonte
app.UseMiddleware<ErrorHandlingMiddleware>();
para pouco antesapp.UseStaticFiles();
. A exceção parece ter sido detectada corretamente agora. Isso me leva a acreditar emapp.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
fazer alguma invasão interna de middleware mágico para obter a ordem correta do middleware.O mais recente
Asp.Net Core
(pelo menos da versão 2.2, provavelmente anterior) possui um middleware integrado que facilita um pouco a comparação com a implementação na resposta aceita:Deve fazer o mesmo, apenas um pouco menos de código para escrever.
Importante: Lembre-se de adicioná-lo antes
UseMvc
(ouUseRouting
no .Net Core 3), pois a ordem é importante.fonte
Sua melhor aposta é usar o middleware para obter o log que você está procurando. Você deseja colocar seu log de exceção em um middleware e, em seguida, manipular suas páginas de erro exibidas para o usuário em um middleware diferente. Isso permite a separação da lógica e segue o design que a Microsoft apresentou com os dois componentes de middleware. Aqui está um bom link para a documentação da Microsoft: Tratamento de erros no ASP.Net Core
Para seu exemplo específico, convém usar uma das extensões no middleware StatusCodePage ou criar o seu próprio dessa maneira .
Você pode encontrar um exemplo aqui para registrar exceções: ExceptionHandlerMiddleware.cs
Se você não gosta dessa implementação específica, também pode usar o ELM Middleware , e aqui estão alguns exemplos: Elm Exception Middleware
Se isso não funcionar para as suas necessidades, você sempre pode rolar o seu próprio componente Middleware observando as implementações do ExceptionHandlerMiddleware e ElmMiddleware para entender os conceitos de criação do seu.
É importante adicionar a exceção que trata do middleware abaixo do statusCodePages, mas acima de todos os outros componentes do middleware. Dessa forma, o middleware Exception capturará a exceção, registre-a e permita que a solicitação continue no middleware StatusCodePage, que exibirá a página de erro amigável para o usuário.
fonte
UseStatusCodePages
seja útil nas implementações de serviços de API da Web. Não há pontos de vista ou HTML em tudo, apenas respostas JSON ...A resposta bem aceita me ajudou muito, mas eu queria passar o HttpStatusCode no meu middleware para gerenciar o código de status do erro em tempo de execução.
De acordo com este link, tive uma idéia para fazer o mesmo. Então, mesclei a resposta Andrei com isso. Então, meu código final está abaixo:
1. Classe base
2. Tipo de classe de exceção personalizada
3. Middleware de exceção personalizada
4. Método de Extensão
5. Configure o método em startup.cs
Agora meu método de login no controlador de conta:
Acima, você pode ver se não encontrei o usuário e, em seguida, criei o HttpStatusCodeException no qual passei o status HttpStatusCode.NotFound e uma mensagem personalizada
no middleware
será bloqueado e passará o controle para
.
Mas e se eu receber um erro de execução antes? Para isso, usei o bloco try catch, que lança a exceção e será capturado no bloco catch (Exception exceptionObj) e passará o controle para
método.
Eu usei uma única classe ErrorDetails para uniformidade.
fonte
startup.cs
novoid Configure(IapplicationBuilder app)
eu recebo um erroIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. E eu adicionei a referência, ondeCustomExceptionMiddleware.cs
está.Para configurar o comportamento de manipulação de exceções por tipo de exceção, você pode usar o Middleware dos pacotes NuGet:
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Exemplo de código:
fonte
Em primeiro lugar, graças a Andrei, pois baseiei minha solução no exemplo dele.
Estou incluindo o meu, pois é uma amostra mais completa e pode economizar tempo para os leitores.
A limitação da abordagem de Andrei é que não lida com o log, capturando variáveis de solicitação potencialmente úteis e negociação de conteúdo (ele sempre retornará JSON, independentemente do que o cliente tenha solicitado - XML / texto sem formatação, etc.).
Minha abordagem é usar um ObjectResult que nos permita usar a funcionalidade inserida no MVC.
Esse código também impede o armazenamento em cache da resposta.
A resposta ao erro foi decorada de forma que possa ser serializada pelo serializador XML.
fonte
Primeiro, configure o ASP.NET Core 2
Startup
para executar novamente em uma página de erro os erros do servidor da Web e as exceções não tratadas.Em seguida, defina um tipo de exceção que permita gerar erros nos códigos de status HTTP.
Por fim, em sua controladora para a página de erro, personalize a resposta com base no motivo do erro e se a resposta será vista diretamente pelo usuário final. Este código assume que todos os URLs da API começam com
/api/
.O ASP.NET Core registrará os detalhes do erro para você depurar, portanto, um código de status pode ser tudo o que você deseja fornecer a um solicitante (potencialmente não confiável). Se você quiser mostrar mais informações, pode aprimorá
HttpException
-las para fornecê-las. Para erros de API, é possível colocar informações de erro codificadas em JSON no corpo da mensagem substituindoreturn StatusCode...
porreturn Json...
.fonte
use middleware ou IExceptionHandlerPathFeature está bom. existe outra maneira de eshop
crie um filtro de exceção e registre-o
fonte