2009-09-08 8 views
13

Prenons par exemple un projet avec 10 services et 20 méthodes sur chaque service.WCF: Same Faultcontract sur plusieurs méthodes

Tous les services héritent d'un service de base qui a un contrôle de sécurité. La première chose que chaque méthode fait est de faire un appel à la vérification de sécurité. Cela déclenche une exception de sécurité en cas de problème. Question: Dois-je spécifier un FaultContract sur chaque méthode (OperationContract), ou puis-je le faire une fois dans une définition centrale?

Répondre

6

Non, vous devez le faire sur chaque méthode - WCF est assez difficile et nécessite des paramètres explicites à peu près pour tout (ce qui est vraiment une bonne chose à la fin, je suis convaincu).

Marc

+0

Vous serez certainement d'accord qu'il devrait être possible de mettre en œuvre des préoccupations transversales comme la sécurité de manière orthogonale. Il me semble étrange que je puisse implémenter un bon 'ServiceAuthorizationManager' d'une manière découplée, mais alors je dois aller saupoudrer mes contrats avec le rebut répétitif si je veux jeter une faute de sécurité faite sur commande. –

+0

Je suis d'accord, je cherche une méthode pour faire la jonque répétitive automatiquement, aussi. – joelsand

+0

Vous pouvez écrire quelques T4 pour générer tous vos contrats à partir d'un fichier XML (ou autre) et avoir votre logique personnalisée pour définir les défauts globaux. Il y a aussi le projet [WSSF] (http://servicefactory.codeplex.com/) sur codeplex qui utilise un concepteur pour vos contrats et génère du code client/serveur (c'est un outil assez lourd). – SandRock

0

Oui sur chaque contrat d'exploitation

30

Vous pouvez le faire en créant un attribut personnalisé.

Implémentez IContractBehavior et ajoutez l'erreur à chaque opération de la méthode Validate.

void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
{ 
    foreach (OperationDescription od in contractDescription.Operations) 
     od.Add(yourFault); 
} 

Voici a link qui détaille comment y parvenir. Ci-dessous le code réel à utiliser:

[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] 
public class StandardFaultsAttribute : Attribute, IContractBehavior 
{ 
    // this is a list of our standard fault detail classes. 
    static Type[] Faults = new Type[] 
    { 
     typeof(AuthFailure), 
     typeof(UnexpectedException), 
     typeof(UserFriendlyError) 
    }; 

    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
    } 

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) 
    { 
    } 

    public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
    { 
     foreach (OperationDescription op in contractDescription.Operations) 
     { 
      foreach (Type fault in Faults) 
      { 
       op.Faults.Add(MakeFault(fault)); 
      } 
     } 
    } 

    private FaultDescription MakeFault(Type detailType) 
    { 
     string action = detailType.Name; 
     DescriptionAttribute description = (DescriptionAttribute)    Attribute.GetCustomAttribute(detailType, typeof(DescriptionAttribute)); 

     if (description != null) 
      action = description.Description; 
     FaultDescription fd = new FaultDescription(action); 
     fd.DetailType = detailType; 
     fd.Name = detailType.Name; 
     return fd; 
    } 
} 
+0

+1 Merci, je vais essayer cela sur notre prochain projet –

+0

+1 Cela aide. De cette façon, un attribut peut être appliqué au niveau de l'interface ServiceContract, plutôt qu'à chaque méthode individuelle dans l'interface. – CodingWithSpike

+1

Ceci devrait être marqué comme la réponse. –

Questions connexes