web-dev-qa-db-fra.com

Bonnes pratiques d'exception de service Wcf

Je développe une application distribuée. Il contient des rôles et des ensembles d'autorisations que je dois valider.
Est-ce une bonne pratique de lancer un exception, par exemple, accès non autorisé?
Ou dois-je renvoyer un message au client?

30
marcelo-ferraz

Sur votre opération de service, vous pouvez spécifier un FaultContract qui remplira les deux fonctions comme suit:

[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();

Notez que MyServiceFault doit être marqué avec les attributs DataContract et DataMember, de la même manière que vous le feriez pour un type complexe:

[DataContract]
public class MyServiceFault
{
    private string _message;

    public MyServiceFault(string message)
    {
        _message = message;
    }

    [DataMember]
    public string Message { get { return _message; } set { _message = value; } }
}

Côté service, vous êtes alors en mesure de:

throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));

Et côté client:

try
{
    ...
}
catch (FaultException<MyServiceFault> fault)
{
    // fault.Detail.Message contains "Unauthorized Access"
}
53
Traxxus

Eh bien, vous pouvez intercepter toutes les exceptions dans les méthodes d'implémentation du service WCF et les renvoyer en tant que FaultExceptions. En procédant de cette façon, l'exception sera renvoyée au client avec un message de votre choix:

[OperationContract]
public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (Exception ex)
    {
        // Log the exception including stacktrace
        _log.Error(ex.ToString());

        // No stacktrace to client, just message...
        throw new FaultException(ex.Message);
    }
}

Pour éviter que des erreurs inattendues ne soient transmises au client, il est également recommandé de ne jamais lancer d'instances d'exception dans le code côté serveur. Au lieu de cela, créez un ou plusieurs de vos propres types d'exception et lancez-les. Ce faisant, vous pouvez faire la distinction entre les erreurs de traitement du serveur inattendues et les erreurs générées en raison de demandes non valides, etc.:

public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (MyBaseException ex)
    {
         // This is an error thrown in code, don't bother logging it but relay
         // the message to the client.
         throw new FaultException(ex.Message);
    }
    catch (Exception ex)
    {
        // This is an unexpected error, we need log details for debugging
        _log.Error(ex.ToString());

        // and we don't want to reveal any details to the client
        throw new FaultException("Server processing error!");
    }
}
12
Daniel Persson

Si vous n'utilisez pas basicHTTPBinding ... pour éviter cela, vous devez toujours lancer FaultException = du service ... de votre bloc de capture, utilisez simplement:

throw new FaultException("Your message to the clients");
2
khaled4vokalz