web-dev-qa-db-fra.com

Gestion des erreurs ASP.Net Core 2: comment renvoyer les détails d'exception formatés dans Http Response?

Je cherche un moyen de retourner les détails de toute exception qui se produit lors de l'appel d'une méthode de mon API Web.

Par défaut dans l'environnement de production, l'erreur 500 "Erreur de serveur interne" est la seule information renvoyée par l'API.

Il s'agit d'une API privée qui n'est pas publiée sur Internet et l'application appelante doit obtenir et stocker tous les détails en cas d'exception.

Les détails de l'exception peuvent être JSON formatés dans le contenu HttpResponse, permettant à l'appelant de lire Message et l'attribut StackTraceString de l'exception (pas de page HTTP comme configuration UseDeveloperExceptionPage ).

Actuellement, la méthode de configuration de démarrage par défaut est:

public class Startup
{   
    [...]

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory)
    {
        loggerFactory.AddNLog();
        env.ConfigureNLog(Path.Combine(AppContext.BaseDirectory, "nlog.config"));

        if ( env.IsDevelopment() )
            app.UseDeveloperExceptionPage();
        else
            app.UseStatusCodePages();

        app.UseMvc();
    }
}
14
Anthony Brenelière

Vous pouvez écrire un middleware personnalisé, qui intercepte toutes les exceptions et les renvoie à l'appelant:

public class ExceptionHandler
{
    private readonly RequestDelegate _next;

    public ExceptionHandler(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        var response = context.Response;
        response.ContentType = "application/json";
        response.StatusCode = (int)HttpStatusCode.InternalServerError;
        await response.WriteAsync(JsonConvert.SerializeObject(new
        {
            // customize as you need
            error = new
            {
                message = exception.Message,
                exception = exception.GetType().Name
            }
        }));
    }
}

et enregistrez-le dans votre méthode de configuration de démarrage:

if (env.IsDevelopment())
    app.UseDeveloperExceptionPage();
else
   app.UseMiddleware<ExceptionHandler>();
20
CommonGuy

Alternativement au middleware, vous pouvez créer ActionFilterAttribute et modifier IActionResult

Voici un exemple simple attribué que pour toutes les exceptions non gérées renvoie 400 Bad request avec la méthode Exception.

public class MyUnhandledExceptionFilter : ActionFilterAttribute, IExceptionFilter
{        
    public void OnException(ExceptionContext context)
    {           
        context.Result = new BadRequestObjectResult(context.Exception.Message);
    }
}

Vous l'enregistrez ensuite dans la méthode ConfigureServices du démarrage comme celle-ci

services.AddMvc(options =>
        {
            options.Filters.Add(typeof(MyUnhandledExceptionFilter));
        })

Cela ne capture que les exceptions qui ont atteint MVC, ce qui dans la plupart des cas est ce dont vous avez besoin

8
Vitaly