Turn off WS-Policy in WCF ...
"Microsoft non supporta gli standard". Quante volte avete sentito questa frase? Parecchie ... e specialmente pronunciata da sviluppatori non-Microsoft (Java?). Ora, lungi da me fare una critica, ma ora che gli standard sono (quasi) tutti supportati, mi trovo di fronte tool "dell'altra parte" che non li supportano. Alcune versioni di Axis (non so essere più preciso, purtroppo), per esempio, non supportano WS-Policy e nella generazione dei relativi proxy client non vogliono neanche vederlo nel wsdl. Dico io, ma almeno ignoralo
!!!
Comunque sia, per questi motivi mi sono trovato nella situazione di dover disabilitare la generazione del WS-Policy. Per farlo è bastato seguire alcuni passi per rimuovere (non disabilitare a monte, purtroppo) dal flusso di output la generazione di WS-Policy.
La soluzione che alla fine ho adottato è composta da un attributo che implementa le interfacce IWsdlExportExtension e IContractBehavior e che posto sull'implementazione del mio servizio mi consentono di intervenire nel flusso di controllo dell'output WSDL.
Dalla prima interfaccia ho a disposizione due metodi: ExportContract e ExportEndpoint. Nel secondo metodo che, come dice il nome, opera a livello di endpoint, ho aggiunto il codice che rimuove dalle extensions il tag wsp:Policy, rimuove il wsp:PolicyReference e infine la dichiarazione del namespace. Questo è il codice utilizzato:
1 public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
2 {
3 // Recupero l'istanza di ServiceDescription
4 System.Web.Services.Description.ServiceDescription sd = context.WsdlBinding.ServiceDescription;
5
6 // Rimuovo l'estensione WS-Policy
7 XmlElement policy = sd.Extensions.Find("Policy", "http://schemas.xmlsoap.org/ws/2004/09/policy");
8 if (policy != null)
9 {
10 int i = sd.Extensions.IndexOf(policy);
11 context.WsdlBinding.ServiceDescription.Extensions.RemoveAt(i);
12 }
13
14 // Rimuovo il riferimento WS-PolicyReference
15 System.Web.Services.Description.Binding b = sd.Bindings[context.WsdlBinding.Name];
16 XmlElement policyReference = b.Extensions.Find("PolicyReference", "http://schemas.xmlsoap.org/ws/2004/09/policy");
17 if (policyReference != null)
18 {
19 int i = b.Extensions.IndexOf(policyReference);
20 b.Extensions.RemoveAt(i);
21 }
22
23 // Rimuovo la dichiarazione del namespace
24 XmlQualifiedName[] ns = sd.Namespaces.ToArray();
25 ArrayList list = new ArrayList(ns);
26
27 XmlQualifiedName wsp = new XmlQualifiedName("wsp", "http://schemas.xmlsoap.org/ws/2004/09/policy");
28 if (wsp != null)
29 {
30 int i = list.IndexOf(wsp);
31 list.RemoveAt(i);
32
33 ns = (XmlQualifiedName[])list.ToArray(typeof(XmlQualifiedName));
34 sd.Namespaces = new XmlSerializerNamespaces(ns);
35 }
36
37 }
38
Per il nostro scopo non è importante vedere il codice dei restanti metodi. Ora è sufficiente decorare il servizio dal quale vogliamo rimuovere le WS-Policy con l'attributo creato. Per esempio:
1 [WsdlController()]
2 public class MyService : IService1
3
Probabilmente, anzi sicuramente, il codice può essere migliorato. Personalmente non ho ancora avuto difficoltà con i vari tool di validazione sul WSDL generato ne tantomeno con l'svcutil nella generazione di un client di prova. Segnalatemi perciò eventuali problemi, osservazioni o dubbi sul codice o sulla metodologia utilizzata.