Andrea "Kiraya"Magini

IT Professional Master

Single post

Consumare Wcf con configurazione programmatica (senza toccare il web.config)

Le Windows Communication Foundation permettono una configurazione molto semplice e efficace, risolvendo in automatico i binding e tutte le configurazioni di channel, porte e quanto altro direttamente leggendo da web.config oppure da un app.config.
Il problema nasce quando andiamo a utilizzare ad esempio un client verso un servizio wcf , direttamente in delle application pages o webpart all’interno di Sharepoint.
In questo caso la configurazione può essere gestita in 3 modi:
Nel primo caso dobbiamo mettere mano al web.config di Sharepoint, in quanto le application pages e/o le webpart sono hostate all’interno della sua Web Applicaiton, e questo per motivi di policy, non sempre è possibile.
[cce lang=”xml”]
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name=”RichiestaDatiSoapBinding” closeTimeout=”00:01:00″
openTimeout=”00:01:00″ receiveTimeout=”00:10:00″ sendTimeout=”00:01:00″
allowCookies=”false” bypassProxyOnLocal=”false” hostNameComparisonMode=”StrongWildcard”
maxBufferSize=”2147483647″ maxBufferPoolSize=”524288″ maxReceivedMessageSize=”2147483647″
messageEncoding=”Text” textEncoding=”utf-8″ transferMode=”Buffered”
useDefaultWebProxy=”true”>
<readerQuotas maxDepth=”32″ maxStringContentLength=”2147483647″ maxArrayLength=”16384″
maxBytesPerRead=”4096″ maxNameTableCharCount=”16384″ />
<security mode=”None”>
<transport clientCredentialType=”None” proxyCredentialType=”None”
realm=”” />
<message clientCredentialType=”UserName” algorithmSuite=”Default” />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address=”http://localhost:81/testservice/servizio.asmx” binding=”basicHttpBinding” bindingConfiguration=”RichiestaDatiSoapBinding”
contract=”TestService.RichiestaDatiSoapBinding” name=”RichiestaDatiSoapBinding” />
</client>
</system.serviceModel>
[/cce]
Il secondo meccanismo , messo a disposizione direttamente dalle Api di Sharepoint, prevede l’utilizzo delle SPWebConfigModification Api, che permettonod i manipolare il web.config di iis, mediante codice, andando ad aggiungere le parti che servono in fase , ad esempio, di attivazione di una feature.. A mio avviso questa parte è qualcosa di veramente terrificante, perche si arriva ad ottenere un web.config spesso illeggibile e quasi sempre non funzionante e oltretutto difficile da controllare visto che tutto il value che deve essere passato al configModification deve avere l’escape di tutti i caratteri particolari.. quindi pieno di entity xml come il @quot …
[cce lang=”csharp”]
SPWebConfigModification modificaWebConfig= new SPWebConfigModification();
modificaWebConfig.Path = “configuration/system.serviceModel”;
modificaWebConfig.Sequence = 0;
modificaWebConfig.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
modificaWebConfig.Owner = System.Threading.Thread.CurrentPrincipal.Identity.Name;
modificaWebConfig.Value = @”<bindings><basicHttpBinding>..etc.etc..inserire qui tutto l’xml del binding”;
SPWebService service = SPWebService.ContentService;
service.WebConfigModifications.Add(modificaWebConfig);
service.Update();
service.ApplyWebConfigModifications();
[/cce]
Un terzo modo è quello di creare una classe che fornisca direttamente il Binding (BasicHttpBinding) e l’Endpoint (EndPointAddess).
Purtroppo per motivi di sicurezza , microsoft ha bloccato la possibilità di leggere l’xml e deserializzarlo nelle relative classi messe a disposizioni dal Framework, quindi la creazione del binding va fatta “a mano”.
I dati possono essere statiticizzati nel codice o ad esempio letti da una Lista di Sharepoint, in cui magari andiamo a memorizzare in un unico Item tutto il blocco xml della configurazione del binding .
 
[cce lang=”csharp”]
public class WCFClientConfiguration
{
public BasicHttpBinding Binding
{
get
{
BasicHttpBinding _binding = new BasicHttpBinding()
{
Name = “ServizioTestSoap”,
CloseTimeout = new TimeSpan(1, 5, 0),
OpenTimeout = new TimeSpan(1, 5, 0),
ReceiveTimeout = new TimeSpan(1, 10, 0),
SendTimeout = new TimeSpan(1, 5, 0),
AllowCookies = false,
BypassProxyOnLocal = true,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferSize = 600000,
MaxBufferPoolSize = 524288,
MaxReceivedMessageSize = 600000,
MessageEncoding = WSMessageEncoding.Text,
TextEncoding = System.Text.Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = false,
ReaderQuotas = new XmlDictionaryReaderQuotas()
{
MaxDepth = 32,
MaxStringContentLength = 500000,
MaxArrayLength = 16384,
MaxBytesPerRead = 4096,
MaxNameTableCharCount = 16384
}
};
_binding.Security.Mode = BasicHttpSecurityMode.Transport;
return _binding;
}
}
public EndpointAddress Endpoint
{
get
{
return new EndpointAddress(“https://localhost:81/testService/service.asmx”);
}
}
}
[/cce]
 
In questo modo quando andiamo a instanziare il nostro client, usiamo il costruttore che accetta in input Binding e Endpoint.
[cce lang=”csharp”]
WcfConfiguration conf = new WCFClientConfiguration();
ServizioTestSoapClient client = new ServizioTestSoapClient (conf.Binding,conf.Endpoint);
[/cce]
Questo permette la memorizzazione ad esempio della configurazione su DB o su altri sistemi di persistenza .