posts - 644, comments - 2003, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

La soluzione definitiva al namespace tempuri.org in WCF 4

I namespace sono fondamentali perché consentono di discriminare due entità che hanno lo stesso nome.
Nella vita reale in nostro namespace è il cognome (questo perché al Concilio di Trento quando sono è stato formalizzato l'uso dei cognomi, il guid non c'era ancora Winking smile).
Nelle classi del Framework il namespace permette di disambiguare un Control tra System.Windows.Forms.Control, System.Windows.Controls e System.Web.UI.
In WCF (ma non solo) il namespace è un Uri ma non necessariamente indica una risorsa esistente (vale a dire che il namespace http://schemas.iamraf.net/Calculator non deve essere una risorsa esistente in rete).

Alla creazione di un progetto WCF, Visual Studio non assegna alcun namespace e di conseguenza le librerie di WCF assegnano automaticamente il valore di http://tempuri.org. Mettere in produzione un servizio con questo namespace implica una alta percentuale di collisione, specie se viene pubblicato su internet. Cambiarlo in un secondo tempo può diventare un incubo perché tutti i proxy devono essere rigenerati. Appare chiaro quindi che l'assegnazione di un namespace sensato è molto importante.

Il modo più semplice per vedere se un servizio si è liberato di tempuri.org, è quello di scaricare i file dei metadati dal servizio utilizzando svcutil utilizzando la command prompt di Visual Studio (o del Framework.NET sdk) in modo che le variabili di environment conoscano la path del tool svcutil:

X:\Temp>svcutil /t:metadata http://localhost:34422/LabelsService.svc?wsdl
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.1]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 'http://localhost:34422/LabelsService.svc?wsdl' using WS-Metadata Exchange or DISCO.
Saving downloaded metadata files...
X:\Temp\schemas.vevy.com.Printing.wsdl
X:\Temp\tempuri.org.wsdl
X:\Temp\schemas.microsoft.com.2003.10.Serialization.xsd
X:\Temp\schemas.vevy.com.Printing.xsd
X:\Temp\Vevy.PrintEngineGDI.xsd
X:\Temp\schemas.microsoft.com.2003.10.Serialization.Arrays.xsd
X:\Temp\Vevy.Printing.xsd
X:\Temp\System.xsd

Se nella cartella viene generato almeno un file di nome tempuri.org.* significa che abbiamo da qualche parte il namespace di default ci sta affliggendo.

Ma allora come si rimuove tempuri.org?

Per eliminarlo basta assegnare un nostro namespace, e in WCF ci sono tre distinte assegnazioni di namespace.

1. Sul ServiceContract, tipicamente l'interfaccia del servizio:

[ServiceContract(Namespace = "http://schemas.vevy.com/Printing")] public interface ILabelsService {...}

2. Sull'implementazione del servizio, applicando un behavior di tipo ServiceBehavior:

[ServiceBehavior(Namespace = "http://schemas.vevy.com/Printing")] public class LabelsService : ILabelsService { ... }

3. Sull'Endpoint che deve assegnare il namespace del Binding

<endpoint address="net.pipe://localhost/LabelsService" binding="netNamedPipeBinding" bindingConfiguration="Binding1" name="PipeEndpoint" bindingNamespace="http://schemas.vevy.com/Printing" contract="..." />

Personalmente ritengo che questo diverso trattamento del namespace del binding suoni un po' come un'inconsistenza.
Fino alla versione 3.5, l'assegnazione di bindingNamespace non era un problema ma adesso, nella versione 4, WCF permette la configurazione semplificata e non è più necessario esplicitare l'endpoint o addirittura si può omettere completamente la configurazione, lasciando i default.

La configurazione semplificata di WCF 4 non si limita a impostare dei valori di default, ma permette di stabilire quali sono i default per behavior, i binding e i protocolli di tutti i servizi per quell'host. Il problema è già stato segnalato.

E qui le cose si complicano ancora di più. Quando il servizio viene messo in host su IIS molte delle impostazioni del servizio vengono totalmente ignorate e tra queste bindingNamespace.

Sembrava un ginepraio da cui non poter venire fuori, sembrava che ci saremmo dovuti accontentare di avere un namespace impostato a tempuri.org.

Ho trovato una soluzione banale di cui non ho trovato traccia in giro, tanto che puzza di bruciato, ma funziona.

Perciò ecco di nuovo il punto 3.

3. (revisited) Scrivere un Service Behavior che sostituisce il namespace al volo:

public class BindingNamespaceBehavior : Attribute, IServiceBehavior { public string bindingNamespace { get; set; } public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { } public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { foreach (var endpoint in serviceHostBase.Description.Endpoints) { endpoint.Binding.Namespace = bindingNamespace; } } }

 

Fatto questo, è sufficiente applicare l'attributo sull'implementazione del servizio (senza toccare la configurazione in alcun modo) che diventa perciò:

[ServiceBehavior(Namespace = "http://schemas.vevy.com/Printing")] [BindingNamespaceBehavior(bindingNamespace = "http://schemas.vevy.com/Printing")] public class LabelsService : ILabelsService { ... }

Non era semplice? Forse troppo?

A questo punto basta ri-scaricare i metadati con svcutil per verificare che tempuri.org sia definitivamente sparito.

Happy namespace everybody!

Print | posted on giovedì 10 febbraio 2011 16:22 |

Feedback

Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

@Nicolò. Posso anche parlare di castelli di sabbia che i malpensanti sono sempre in pole position, quindi ... ;)
11/02/2011 02:32 | Raffaele Rialdi
Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

Bel post.
Mi piace come hai parlato di un concetto molto trascurato (la gestione dei namespace) e di come poi l'hai calato nella realtà del "coder" quotidiano.

Bello.
Grazie.
11/02/2011 13:29 | Omar Damiani
Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

Grazie Omar :)
12/02/2011 17:47 | Raffaele Rialdi
Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

Hi there,

Thanks for this! after spending 4 hours trying to get rid of the annoying tempuri.org namespace I finally managed to get it done, thanks to your code!

Just had to add this "using System.ServiceModel.Description;" and paste you class into my code.

Cheers,
Rui

12/10/2016 20:53 | Rui
Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

This blog is better for those who want to do better their work. when they are follow these rushmypapers.me page they can get help. And they improve their working style as the other needs.
16/10/2017 14:03 | Jarlison
Gravatar

# re: La soluzione definitiva al namespace tempuri.org in WCF 4

good article
29/06/2018 10:25 | good
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET