2009-09-08 17 views
13

Tome por ejemplo un proyecto con 10 servicios y 20 métodos en cada servicio.WCF: Same Faultcontract en muchos métodos

Todos los servicios heredan de un servicio base que tiene un control de seguridad. Lo primero que hace cada método es hacer una llamada al control de seguridad. Esto arroja una excepción de seguridad si hay un problema.

La pregunta es: ¿Necesito especificar un FaultContract en cada método (OperationContract), o puedo hacerlo una vez en una definición central?

Respuesta

6

No, tiene que hacerlo en todos y cada método - WCF es bastante exigente y requiere ajustes explícitos prácticamente para todo (que en realidad es una buena cosa, al final, me estoy convencido).

Marc

+0

Seguramente estarías de acuerdo en que debería ser posible implementar cuestiones transversales como la seguridad de una manera ortogonal. Me parece extraño que pueda implementar un buen 'ServiceAuthorizationManager' de manera desacoplada, pero luego tengo que rociar mis contratos con basura repetitiva si quiero lanzar un error de seguridad personalizado. –

+0

Estoy de acuerdo, estoy buscando un método para hacer la basura repetitiva automáticamente, también. – joelsand

+0

Puede escribir algo de T4 para generar todos sus contratos desde un archivo XML (u otro) y tener su lógica personalizada para definir fallas globales. También está el proyecto [WSSF] (http://servicefactory.codeplex.com/) en codeplex que usa un diseñador para sus contratos y genera código de cliente/servidor (es una herramienta bastante pesada). – SandRock

0

Sí en cada contrato de operación

30

Puede hacerlo creando un atributo personalizado.

Implemente IContractBehavior y agregue el error a cada operación en el método Validate.

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

Aquí está a link que detalla cómo lograr esto. Debajo del código real para usar:

[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 Gracias, probaré esto en nuestro próximo proyecto –

+0

+1 Esto ayuda. De esta forma, el atributo 1 se puede aplicar al nivel de interfaz de ServiceContract, en lugar de a cada método individual en la interfaz. – CodingWithSpike

+1

Esto debe marcarse como la respuesta. –

Cuestiones relacionadas