Activez IncludeExceptionDetailInFaults (à partir de ServiceBehaviorAttribute ou du comportement de configuration <serviceDebug>) sur le serveur

157

J'ai un service WCF qui fonctionne parfaitement, et quelque chose a changé et je ne sais pas quoi.

J'obtiens cette exception:

System.ServiceModel.FaultException: le serveur n'a pas pu traiter la demande en raison d'une erreur interne. Pour plus d'informations sur l'erreur, activez IncludeExceptionDetailInFaults (à partir de ServiceBehaviorAttribute ou du comportement de configuration) sur le serveur afin de renvoyer les informations d'exception au client, ou activez le traçage selon la documentation du SDK Microsoft .NET Framework 3.0 et inspectez les journaux de suivi du serveur.

C'est déroutant car j'utilise .NET 4.0.

Où dois-je allumer IncludeExceptionDetailInFaults? Je me bats pour le trouver.

Trevor
la source

Réponses:

265

Définissez un comportement dans votre .configfichier:

<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="debug">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    ...
  </system.serviceModel>
</configuration>

Appliquez ensuite le comportement à votre service en suivant ces lignes:

<configuration>
  <system.serviceModel>
    ...
    <services>
      <service name="MyServiceName" behaviorConfiguration="debug" />
    </services>
  </system.serviceModel>
</configuration>

Vous pouvez également le définir par programme. Voir cette question .

Otiel
la source
1
Salut Otivel, mon cas, il y a des dossiers imbriqués contenant différents sites et services. Le dossier où réside mon service et où j'obtiens une erreur est au troisième degré d'imbrication par rapport à l'application Web principale et j'ai dédié web.config pour chaque service. Je change mon web.config correspondant en conséquence pour ajouter <serviceDebug includeExceptionDetailInFaults = "true" />. Mais j'obtiens toujours l'erreur. Dois-je changer tout le web.config dans une application Web complète?
MaxRecursion
2
@AkshayKulkarni: Pas sûr, je n'ai pas d'expérience avec votre cas. Assurez-vous d'abord que vos services ont une référence au serviceBehavior (vérifiez la réponse de gagogra ). Si cela ne résout pas le problème, posez une question sur SO.
Otiel
1
@MatthewLock: réponse mise à jour. Vérifiez également <comportement> et <service> si vous avez besoin de plus de détails.
Otiel
1
Visual Studio me dit que serviceBehaviors ne peut pas être un enfant direct de system.serviceModel. J'ai fini par aller avec la réponse de rich.okelly.
andrewb
3
Remarque: VS2013 place la balise <serviceDebug> dans le Web.config par défaut avec la valeur false. Si vous ne remarquez pas comme je ne l'ai pas fait et ajoutez le XML ci-dessus, apparemment, ce qui est en dernier dans le fichier l'emporte. J'espère que cela sera utile à quelqu'un là-bas.
Jeff
63

C'est dans le fichier app.config.

<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceDebug includeExceptionDetailInFaults="true"/>
Rich O'Kelly
la source
9
Ne définissez pas l'attribut name de <behavior> (comme dans @Otiel answer) si vous voulez qu'il s'applique à tous vos services.
Pashec
47

Si vous voulez faire cela par code, vous pouvez ajouter le comportement comme ceci:

serviceHost.Description.Behaviors.Remove(
    typeof(ServiceDebugBehavior));
serviceHost.Description.Behaviors.Add(
    new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
Yang Zhang
la source
Ajoutez ceci à votre ServiceHostinstance d'objet: Exemple:ServiceHost serviceHost = new ServiceHost(Program.serviceInstance);
Daniel Bonetti
28

Vous pouvez également le définir dans la balise [ServiceBehavior] au-dessus de votre déclaration de classe qui hérite de l'interface

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyClass:IMyService
{
...
}

Immortal Blue a raison de ne pas divulguer les détails de l'exception à une version publiée publiquement, mais à des fins de test, il s'agit d'un outil pratique. Éteignez toujours lorsque vous relâchez.

LievenV
la source
J'ai utilisé ceci dans une application qui s'exécute sur le backend et ne sera jamais visible publiquement, donc cela fonctionne parfaitement
AlbatrossCafe
4

J'obtenais également la même erreur, le WCF fonctionnait correctement pour moi lorsque je l'utilisais dans l'environnement de développement avec mes informations d'identification, mais lorsque quelqu'un d'autre l'utilisait dans TEST, il lançait la même erreur. J'ai fait beaucoup de recherches, puis au lieu de faire des mises à jour de configuration, j'ai géré une exception dans la méthode WCF à l'aide de l'exception d'erreur. L'identité du WCF doit également être définie avec les mêmes informations d'identification que celles qui ont accès à la base de données, quelqu'un peut avoir changé votre autorité. Veuillez trouver ci-dessous le code pour le même:

 [ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(ServiceData))]
    ForDataset GetCCDBdata();

    [OperationContract]
    [FaultContract(typeof(ServiceData))]
    string GetCCDBdataasXMLstring();


    //[OperationContract]
    //string GetData(int value);

    //[OperationContract]
    //CompositeType GetDataUsingDataContract(CompositeType composite);

    // TODO: Add your service operations here
}

  [DataContract]
public class ServiceData
{
    [DataMember]
    public bool Result { get; set; }
    [DataMember]
    public string ErrorMessage { get; set; }
    [DataMember]
    public string ErrorDetails { get; set; }
}

dans votre service1.svc.cs, vous pouvez utiliser ceci dans le bloc catch:

 catch (Exception ex)
        {
            myServiceData.Result = false;
            myServiceData.ErrorMessage = "unforeseen error occured. Please try later.";
            myServiceData.ErrorDetails = ex.ToString();
            throw new FaultException<ServiceData>(myServiceData, ex.ToString());
        }

Et utilisez ceci dans l'application client comme le code ci-dessous:

  ConsoleApplicationWCFClient.CCDB_HIG_service.ForDataset ds = obj.GetCCDBdata();

            string str = obj.GetCCDBdataasXMLstring();

        }

        catch (FaultException<ConsoleApplicationWCFClient.CCDB_HIG_service.ServiceData> Fex)
      {
          Console.WriteLine("ErrorMessage::" + Fex.Detail.ErrorMessage + Environment.NewLine);
          Console.WriteLine("ErrorDetails::" + Environment.NewLine + Fex.Detail.ErrorDetails);
          Console.ReadLine();
      }

Essayez simplement ceci, cela aidera à coup sûr à obtenir le problème exact.

Aditya
la source
4
Vous ne devez PAS exposer les détails de l'exception sous-jacente. Le but de la séparation des exceptions entre le client et le serveur et la nécessité de cet indicateur est d'empêcher que les informations d'exception soient mises à la disposition du client. Un utilisateur malveillant pourrait utiliser ces informations pour manipuler votre service! Si vous développez, utilisez le comportement IncludeExceptionDetailInFaults comme décrit pour propager l'exception entière, ou dans le déploiement, déclenchez une exception faultexception donnant une erreur très basique, telle que "Impossible d'enregistrer le fichier" plutôt que de donner une trace de la pile et des détails complets sur le exception.
Immortal Blue
Salut .. dans mon cas, toutes les autres fonctions de service sont appelées par la fonction que j'utilise pour enregistrer le fichier lève cette exception ... pour connaître le problème exact que j'ai utilisé le système de journalisation mais aucun journal n'est créé pour cette méthode ... im création de 3 journaux 1) lorsque le service a frappé 2) avant d'enregistrer un fichier et 3) journal des exceptions.
user3217843
0

Comme les informations d'erreur l'ont indiqué en premier, essayez d'augmenter la valeur du délai d'expiration du côté client et du côté service comme suit:

<basicHttpBinding>
    <binding name="basicHttpBinding_ACRMS" maxBufferSize="2147483647"
      maxReceivedMessageSize="2147483647"
      openTimeout="00:20:00" 
      receiveTimeout="00:20:00" closeTimeout="00:20:00"
      sendTimeout="00:20:00">
      <readerQuotas maxDepth="32" maxStringContentLength="2097152"
        maxArrayLength="2097152" maxBytesPerRead="4006" maxNameTableCharCount="16384" />
    </binding>

Alors n'oubliez pas d'appliquer cette configuration de liaison au point de terminaison en procédant comme suit:

<endpoint address="" binding="basicHttpBinding" 
      bindingConfiguration="basicHttpBinding_ACRMS"
      contract="MonitorRAM.IService1" />

Si ce qui précède ne peut pas aider, ce sera mieux si vous pouvez essayer de télécharger votre projet principal ici, alors je veux avoir un test à mes côtés.

Muhammad Mohsin Muneer
la source