276 votes

Comment renvoyer HTTP 500 à partir de l'Api Web ASP.NET Core RC2 ?

Dans la RC1, je faisais ça :

[HttpPost]
public IActionResult Post([FromBody]string something)
{    
    try{
        // ...
    }
    catch(Exception e)
    {
         return new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError);
    }
}

Dans la RC2, il n'y a plus de HttpStatusCodeResult, et il n'y a rien que je puisse trouver qui me permette de retourner un type 500 de IActionResult.

L'approche est-elle désormais totalement différente pour ce que je demande ? Ne faisons-nous plus de try-catch dans Controller code ? Doit-on simplement laisser le framework renvoyer une exception 500 générique à l'appelant de l'API ? Pour le développement, comment puis-je voir la pile d'exceptions exacte ?

331voto

Federico Dipuma Points 10561

D'après ce que je peux voir, il y a des méthodes d'aide à l'intérieur de l'interface utilisateur. ControllerBase classe. Il suffit d'utiliser le StatusCode méthode :

[HttpPost]
public IActionResult Post([FromBody] string something)
{    
    //...
    try
    {
        DoSomething();
    }
    catch(Exception e)
    {
         LogException(e);
         return StatusCode(500);
    }
}

Vous pouvez également utiliser le StatusCode(int statusCode, object value) qui négocie également le contenu.

9 votes

En faisant cela, nous perdons les en-têtes CORS, donc les erreurs sont cachées aux clients du navigateur. C'est frustrant.

3 votes

@bbsimonbb Les erreurs internes doivent être cachées aux clients. Elles doivent être enregistrées pour les développeurs.

22 votes

Les développeurs devraient avoir, et ont traditionnellement eu, la prérogative de choisir le niveau d'information sur les erreurs à renvoyer.

232voto

Edward Comeau Points 1751

Vous pourriez utiliser Microsoft.AspNetCore.Mvc.ControllerBase.StatusCode y Microsoft.AspNetCore.Http.StatusCodes pour former votre réponse, si vous ne souhaitez pas coder en dur des numéros spécifiques.

return  StatusCode(StatusCodes.Status500InternalServerError);

MISE À JOUR : août 2019

Ce n'est peut-être pas directement lié à la question initiale, mais en essayant d'obtenir le même résultat avec Microsoft Azure Functions J'ai découvert que je devais construire une nouvelle StatusCodeResult trouvé dans le Microsoft.AspNetCore.Mvc.Core assemblage. Mon code ressemble maintenant à ceci ;

return new StatusCodeResult(StatusCodes.Status500InternalServerError);

14 votes

C'est une excellente solution, qui évite les parties codées en dur et les "chiffres magiques". J'ai déjà utilisé StatusCode((int)HttpStatusCode.InternalServerError), mais je préfère le vôtre.

2 votes

Une chose à laquelle je n'ai pas pensé à l'époque, c'est que cela rend le code plus lisible. En y revenant, vous savez à quoi correspond l'erreur 500, c'est juste là dans le code. L'auto-documentation :-)

21 votes

Je ne peux pas imaginer que l'erreur de serveur interne (500) change de sitôt.

76voto

David McEleney Points 1104

Si vous avez besoin d'un corps dans votre réponse, vous pouvez appeler

return StatusCode(StatusCodes.Status500InternalServerError, responseObject);

Ceci retournera un 500 avec l'objet de réponse...

8 votes

Si vous ne voulez pas créer un type d'objet de réponse spécifique : return StatusCode(StatusCodes.Status500InternalServerError, new { message = "error occurred" }); Et bien sûr, vous pouvez ajouter un message aussi descriptif que vous le souhaitez, ainsi que d'autres éléments.

24voto

gldraphael Points 635

Une meilleure façon de gérer ce problème à partir de maintenant (1.1) est de le faire dans la section Startup.cs 's Configure() :

app.UseExceptionHandler("/Error");

Ceci exécutera la route pour /Error . Cela vous évitera d'ajouter des blocs try-catch à chaque action que vous écrivez.

Bien sûr, vous devrez ajouter un ErrorController similaire à celui-ci :

[Route("[controller]")]
public class ErrorController : Controller
{
    [Route("")]
    [AllowAnonymous]
    public IActionResult Get()
    {
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

Plus d'informations aquí .


Si vous souhaitez obtenir les données d'exception réelles, vous pouvez ajouter ceci à l'élément ci-dessus Get() juste avant le return déclaration.

// Get the details of the exception that occurred
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();

if (exceptionFeature != null)
{
    // Get which route the exception occurred at
    string routeWhereExceptionOccurred = exceptionFeature.Path;

    // Get the exception that occurred
    Exception exceptionThatOccurred = exceptionFeature.Error;

    // TODO: Do something with the exception
    // Log it with Serilog?
    // Send an e-mail, text, fax, or carrier pidgeon?  Maybe all of the above?
    // Whatever you do, be careful to catch any exceptions, otherwise you'll end up with a blank page and throwing a 500
}

L'extrait ci-dessus est tiré de Le blog de Scott Sauber .

0 votes

C'est génial, mais comment puis-je enregistrer l'exception qui a été levée ?

0 votes

@redwards510 Voici comment faire : scottsauber.com/2017/04/03/ Je vais mettre à jour ma réponse pour le refléter, car c'est un cas d'utilisation très courant.

0 votes

@gldraphael Nous utilisons actuellement Core 2.1. Le blog de Scott est génial, mais je suis curieux de savoir si l'utilisation de IExceptionHandlerPathFeature est actuellement la meilleure pratique recommandée. Peut-être que la création d'un middleware personnalisé est préférable ?

22voto

Shimmy Points 23393
return StatusCode((int)HttpStatusCode.InternalServerError, e);

Doit être utilisé dans des contextes non-ASP.NET (voir les autres réponses pour ASP.NET Core).

HttpStatusCode est une énumération dans System.Net .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X