<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Nuovo blog</title>
        <link>http://blogs.ugidotnet.org/duke/Default.aspx</link>
        <description>Another Subtext Powered Blog</description>
        <language>it-IT</language>
        <copyright>Blog Author</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <image>
            <title>Nuovo blog</title>
            <url>http://blogs.ugidotnet.org/images/RSS2Image.gif</url>
            <link>http://blogs.ugidotnet.org/duke/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>Condividere ServiceContract tra server .NET e client Silverlight</title>
            <link>http://blogs.ugidotnet.org/duke/archive/2011/08/19/condividere-servicecontract-tra-server-.net-e-client-silverlight.aspx</link>
            <description>&lt;p&gt;Recentemente ho pubblicato su codeplex &lt;a title="SyncWcf" href="http://syncwcf.codeplex.com/" target="_blank"&gt;SyncWcf&lt;/a&gt;, una semplice libreria che consente di risparmiarsi un sacco di seccature quando si vuole consumare un nostro webservice da client Silverlight.&lt;/p&gt;  &lt;p&gt;In particolare questa libreria da il suo meglio nel caso in cui siamo noi a possedere sia il codice lato server (full .NET framework) sia il codice lato client (Silverlight).&lt;/p&gt;  &lt;p&gt;In questo caso siamo spesso costretti ad accrocchi strani e poco funzionali: essendo Silverlight pensato per funzionare sempre in modo asincrono (giustissimo), si finisce per avere due versioni dell’interfaccia del servizio: una in versione &lt;strong&gt;sincrona&lt;/strong&gt; e una &lt;strong&gt;asincrona&lt;/strong&gt;, che concettualmente rapresentano però la stessa cosa&lt;/p&gt;  &lt;p&gt;Purtroppo si è costretti a reimplementare per far felice wcf di Silverlight.&lt;/p&gt;  &lt;p&gt;L’alternativa, che mi piace ancora meno, è far generare a visual studio tutto il codice con “add service reference”: questa secondo me è un opzione da considerare solo se il codice server side non è nostro.&lt;/p&gt;  &lt;p&gt;Se stiamo scrivendo noi sia client che server, non ha nessun valore dover riscrivere due volte la stessa interfaccia solo per far felice wcf di Silverlight: ed ecco dove SyncWcf ci viene in aiuto.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;SyncWcf si compone principalmente di due classi: una AsyncChannelFactory che fa il verso alla ChannelFactory di wcf (e che usa internamente) ed un AsyncChannel (che è suo fratello dell’ *Channel di wcf, come si può ben immaginare, e che usa internamente).&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h3&gt;Ecco come funziona:&lt;/h3&gt;  &lt;p&gt;SyncWcf si occupa per prima cosa di trasformare l’interfaccia “sincrona” usata sul server in una che implementi l’AsyncPattern con Begin-  ed End- per ogni operazione, essendo un pattern ci riesce benissimo da solo senza bisogno di intelligenza ed errori umani.&lt;/p&gt;  &lt;p&gt;Fatto questo la da in pasto alla solita ChannelFactory che tutta contenta ritorna un *Channel.&lt;/p&gt;  &lt;p&gt;Tuttavia sarebbe duro usare questo channel dal nostro codice visto che si basa su un tipo generato a runtime.&lt;/p&gt;  &lt;p&gt;Per questo il channel generato viene wrappato da un AsyncChannel il quale aggiunge l’ultimo pezzo al puzzle: si occupa di coordinare la chiamata ai metodi Begin ed End (e fare il dispatching sul thread corretto) nel modo corretto,  semplicemente &lt;strong&gt;usando la versione sincrona&lt;/strong&gt; dell’interfaccia del servizio come traccia, che&lt;strong&gt; a questo punto può essere messa in un &lt;u&gt;portable assembly&lt;/u&gt; e condivisa tra server e client.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ecco un esempio di come apparirebbe il vostro codice per chiamare un metodo di un servizio nel caso decidiate di usare SyncWcf:&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e092a7e0-42c0-43dc-acdd-98a27a6c65f9" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="js"&gt;var channel = new AsyncChannelFactory&amp;lt;ITestService&amp;gt;().CreateChannel();

channel.ExecuteAsync(
    ws =&amp;gt; ws.Operation(1),
    result =&amp;gt;
    {
         // [...] Do something with the result
    });&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Qui “ws” è il nome che ho dato alla variabile che rappresenta il mio webservice, e che &lt;u&gt;è del tipo dell’interfaccia ITestService&lt;/u&gt; (quella del server! non una copia o codice generato…), I parametri sono passati nel modo usuale come se invocassi una qualsiasi funzione (niente array di parametri o simili)&lt;/p&gt;

&lt;p&gt;Pulito, chiaro, semplice da manutenere, ed assolutamente sincronizzato tra server e client, visto che l’interfaccia può essere la stessa e quindi condivisa in un portable assembly: non correrete mai il rischio di fare refactoring sul server e dimenticarvi di aggiornare la rispettiva altra metà sul client.&lt;/p&gt;

&lt;p&gt;Un altra cosetta importante: &lt;strong&gt;funzionano anche&lt;/strong&gt; chiamate ad operazioni con parametri &lt;strong&gt;out&lt;/strong&gt; e &lt;strong&gt;ref&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A me piace parecchio! lavoro con persone che non hanno mai visto Silverlight prima, e sinceramente mi sembra ridicolo proporgli di scrivere interfacce asincrone e poi codice oscuro e illegibile coi dispatcher per fare una semplicissima invocazione ad un webservice: giusto per divertimento, ecco cosa avrei dovuto scrivere invece di queste semplici 8 (sono 7 in realtà) righe se non avessi SyncWcf&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a2c31620-ba80-411d-97ae-92f2c651705c" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c"&gt;[ServiceContract]
public interface ITestService
{
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginOperation(int value, AsyncCallback callback, object state);

    int EndOperation(IAsyncResult result);
}

ITestService testService = new ChannelFactory&amp;lt;ITestService&amp;gt;("*").CreateChannel();
// [...]
AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    int value = ((int)result.AsyncState).EndOperation(result);
    this.Dispatcher.BeginInvoke(delegate
    {
        // [...] Do something with the result
    });
};
testService.BeginOperation(1, asyncCallBack, testService);&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;hmmm… considerando che qua c’è solo un Operation… e che è un caso assolutamente &lt;strong&gt;semplice ed irreale&lt;/strong&gt;, andare per la strada nativa in silverlight mi pare un opzione assolutamente impaticabile&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In sostanza con SyncWcf ottengo due risultati &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;consentire anche ai neofiti di chiamare webservice da Silverlight senza nessunissimo sforzo, e praticamente senza niente da imparare, senza rischi che si incasinino coi dispatcher e blocchino l’applicazione. &lt;/li&gt;

  &lt;li&gt;condivido la stessa interfaccia tra server e client, risparmiando tempo ed evitando preblemi del tipo “ho dimenticato di aggiornare la service reference” (che è noioso e mi capita sempre) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Inoltre SyncWcf si compone di 4 classi delle quali: &lt;strong&gt;due&lt;/strong&gt; sono helper interni con cui l’utilizzatore non dovrebbe aver mai niente a che fare, e altri &lt;strong&gt;due&lt;/strong&gt; sono wrapper che si comportano concettualmente come ChannelFactory e *Channel di Wcf, ma semplificando enormemente le cose.&lt;/p&gt;

&lt;p&gt;È perciò estremamente leggera , e semplice da imparare e non ha dipendenze da nessuna libreria di terze parti (chi ha detto Castle? No, neanche quella).&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Ultimo: totale supporto all’intisense, io adoro premere “.” e vedere cosa posso fare senza dovermi ricordare niente, voi no?&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Tanto per chiaccherare, visto che a questo punto  condividiamo tra server e client l’interfaccia del servizio ed anche I dati, possiamo condividere anche I validatori… e quindi avere il medesimo codice di validazione lato server e client, sempre nel nostro bel portable assembly…o mettere attributi sull’interfaccia del servizio e trovarceli identici sul client visto che è la medesima interfaccia… chesso se uno volesse controllare due claims ogni tanto…. &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ca499616-a44d-4d3d-845b-b3cc4ae17a00" class="wlWriterEditableSmartContent"&gt;Tag di Technorati: &lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Wcf" rel="tag"&gt;Wcf&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Sync" rel="tag"&gt;Sync&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Async" rel="tag"&gt;Async&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Portable+Assembly" rel="tag"&gt;Portable Assembly&lt;/a&gt;,&lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Che ne pensate?&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/duke/aggbug/100282.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Blog Author</dc:creator>
            <guid>http://blogs.ugidotnet.org/duke/archive/2011/08/19/condividere-servicecontract-tra-server-.net-e-client-silverlight.aspx</guid>
            <pubDate>Fri, 19 Aug 2011 18:06:27 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/duke/archive/2011/08/19/condividere-servicecontract-tra-server-.net-e-client-silverlight.aspx#feedback</comments>
            <slash:comments>470</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/duke/comments/commentRss/100282.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/duke/services/trackbacks/100282.aspx</trackback:ping>
        </item>
    </channel>
</rss>