web-dev-qa-db-fra.com

Le message d'exception HTTPError ne s'affiche pas lorsque webapi est exécuté sur le serveur ou exécuté localement

J'ai une webapi qui fonctionne sur un serveur IIS7.5. Il dispose de 3 contrôleurs et tous les 3 peuvent être utilisés pour accéder à la webapi à partir d'appels au sein de mon application.

J'ai eu une erreur lorsque ma classe de base pour mon contrôleur exposait ses fonctions en tant que public, plutôt que protégé. Cela a provoqué le serveur de lever une erreur de serveur interne 500 (en raison d'une exception non valide levée "Plusieurs actions correspondant à la demande ont été trouvées"). Il m'a fallu un certain temps pour approfondir cela, car cela n'a jamais déclenché la journalisation depuis ma webapi. À partir de cette discussion ici , j'ai découvert que l'erreur qui se produisait se produisait avant qu'une fonction Application_Error ne l'attrape pour la consigner . J'ai donc ajouté le code ci-dessous à mon global.asax de ma webapi, et je peux maintenant enregistrer des erreurs comme celle-ci.

MAIS, mon problème maintenant, lorsque je cause une erreur de serveur interne 500 exactement comme ci-dessus, sur ma machine locale exécutant mon webapi, j'obtiens un journal exactement comme je souhaite le voir avec le "ExceptionMessage" de "Plusieurs actions ont été trouvées qui correspondent la demande "expliquée comme la raison de l'erreur interne du serveur. Mais lorsque vous déployez ce code exact sur le serveur et utilisez la webapi à partir de là, mon journal affiche uniquement "Message": "Une erreur s'est produite" et ne m'affiche pas le "ExceptionMessage", même si je peux voir que l'exception est lancé à l'aide de PerfView. J'ai juste besoin de pouvoir obtenir les journaux de mon serveur pour afficher les mêmes informations que ce que mon journal local affiche.

public class ResponseExceptionTrapper : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        return base
            .SendAsync(request, cancellationToken)
            .ContinueWith(response =>
            {
                var result = response.Result;
                if (!result.IsSuccessStatusCode)
                {
                    var exceptionResult = string.Format(
                         "Response exception: \r\n Path({0}) \r\n Status({1}) \r\n",
                         request.RequestUri,
                         result.StatusCode);

                    if (result.Content != null)
                    {
                        var exceptionReadTask =
                               result.Content.ReadAsStringAsync();

                        exceptionReadTask.Wait();
                        exceptionResult += "Message:" +
                                          exceptionReadTask.Result;

                    }

                    // Do something appropriate with exceptionResult
                    exceptionResult.Log();
                }

                return result;
            }, cancellationToken);
    }
}

Exemple de journal de serveur:

Timestamp: 4/24/2014 12:24:40 PM
Message: Timestamp: 4/24/2014 4:24:40 PM
Message: Response exception: 
Path(http://webserver/CreditReporting/Api/RetrieveQueuedPullCreditReport) 
Status(InternalServerError) 
Message:{"Message":"An error has occurred."}

Exemple de journal local:

Timestamp: 4/24/2014 12:03:16 PM
Message: Timestamp: 4/24/2014 4:03:16 PM
Message: Response exception: 
 Path(http://localhost:XXXXX/Api/RetrieveQueuedPullCreditReport) 
 Status(InternalServerError)
 Message:
  {"Message":"An error has occurred.",
  "ExceptionMessage":"Multiple actions were found that match the request:
    \r\nSystem.Threading.Tasks.Task`1[
 Our.WebServices.CreditReporting.Contracts.RetrieveQueuedPullCreditReportResponse] Post
29
cookiekitty

J'ai constaté que ceux-ci devaient être activés dans la configuration globale pour la webapi elle-même:

1: config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly;
2: config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
3: config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;

Le serveur détermine réellement la quantité de détails à afficher, la valeur par défaut est LocalOnly.

Notre méthode de journalisation n'est pas considérée comme locale, je suppose parce qu'elle n'est pas réellement intégrée à l'API elle-même, mais parce qu'elle se trouve dans une DLL partagée entre plusieurs API.

J'ai trouvé this l'article très utile.

59
cookiekitty

J'ai utilisé celui-ci:

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy
          = IncludeErrorDetailPolicy.Always; 

dans Global of API et c'est réussi.

4
ptvce