Visualizzazione post con etichetta WCF. Mostra tutti i post
Visualizzazione post con etichetta WCF. Mostra tutti i post

mercoledì 15 gennaio 2014

HOW TO: WCF - Reusing types in referenced assemblies

Lavorando con i WCF e implementando uno strato di servizio nelle nostre applicazioni, molte volte si rende necessario dover utilizzare i medesimi tipi di dati sul client (DataContract).

In questo articolo vedremo come poter utilizzare la medesima struttura di datacontract tra client e server in ambito di comunicazione WCF.

A seconda del metodo che si preferisce utilizzare, se generare la classe proxy del WCF tramite lo strumento di svcutil o tramite l'aggiunta della Service Reference, gli oggetti utilizzati per effettuare le chiamata al servizio saranno creati in base alla lettura delle informazioni xml contenuti nel wsdl.




Se provassimo ad effettuare una chiamata al servizio tutto funzionerebbe correttamente, ma a tutti gli effetti staremo utilizzando un tipo complesso di dato che tramite la sua serializzazione viene correttamente letto dal server tradotto nel DataContract definito in origine.



Se il client e il server potessero condividere lo stesso DataContract come potremmo fare a utilizzare l'oggetto complesso in entrambi i livelli?


È possibile definire in questo caso le referenze e gli oggetti che il client deve utilizzare per invocare il servizio del WCF.
Sarà quindi necessario che:

1) Il client deve avere la referenza alla class library contenente i data contract



2)Se utilizziamo Visual Studio per aggiungere la service reference, nella sezione advanced, è possibile definire quali assembly condivisi utilizzare per le chiamate al servizio.



in alternativa, se preferiamo utilizzare il comando di svcutil è necessario aggiungere come attributo /reference o /r impostando il path dell'assembly da utilizzare per la generazione della classe proxy.

Il risultato sarà il seguente:



Il client e il server utilizzeranno lo stesso DataContract.
Questo apporta un notevole vantaggio in fase di sviluppo e mantenimento dell'applicazione client server: se dovesse essere necessario aggiungere una property all'interno del data contract, è possibile farlo senza rigenerare la classe proxy o aggiornare il servizio.

In questo modo il data contract può essere gestito e inviato al client senza ulteriori trasformazioni in elementi di DTO, evitando inutile riscrittura di codice.

NB: è possibile generare la classe di proxy anche utilizzando visual studio tramite la "Add service reference".
All'interno della nostra solution sarà presente il file che potremmo includere singolarmente come analogamente faremmo utilizzando il tool di svcutil.




NBB: quanto detto sopra non vale se si utilizza XmlSerializer per il data contract.

link esterni:
http://blogs.msdn.com/b/youssefm/archive/2009/10/09/reusing-types-in-referenced-assemblies-with-svcutil-s-r-switch.aspx

http://paxcel.net/blog/sharing-datacontract-across-wcf-services-without-distributing-separate-copies-to-the-client/

http://msdn.microsoft.com/en-us/library/aa347733(v=vs.110).aspx

venerdì 4 ottobre 2013

HOW TO: Use Transaction over WCF Service

Nel presente articolo, verrà trattata le modalità di utilizzo delle transazioni attraverso i WCF service.

Questa modalità operativa può risultare utile nel caso in cui si utilizzi un layer WCF service per le connessioni e le operazioni alla base dati.

Per utilizzare questo tipo di transazioni avremo bisogno di includere la classe System.Transactions.

Di seguito la reference per capirne il funzionamento:

Per prima cosa sarà necessario abilitare la transazione al nostro servizio. 
Per fare ciò, sarà necessario decorare la firma dei metodi nella nostra interfaccia WCF (ServiceContract) nel seguente modo:

[TransactionFlow(TransactionFlowOption.Allowed)]

Questo permetterà specificare che l'operazione del servizio accetta l'utilizzo delle transazioni da parte del client.
Abilitare quindi la transazione al metodo del servizio, decorandolo con il seguente OperationBehavior:

[OperationBehavior(TransactionScopeRequired = true)]

Configurare il servizio nel seguente modo:

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="TransactionalBind" transactionFlow="true">
          <security mode="None" />
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="Transaction.service">
        <endpoint address="" contract="Transaction.Iservice" binding="wsHttpBinding" bindingConfiguration="TransactionalBind"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="true" />
  </system.serviceModel>


NB: 
  1.  è necessario che il servizio venga esposto con il protocollo di trasporto wsHttpBindings
  2. è necessario specificare l'attributo transactionFlow="true" per permettere l'abilitazione delle transazioni alla connessione wsHttpBindings.
Referenziare sul client il servizio appena creato, settando l'attributo transactionFlow a true:

<binding name="WSHttpBinding_Iservice" transactionFlow="true">

Siamo pronti a questo punto per effettuare le chiamate al nostro servizio.
Faremo ciò utilizzando una transazione che specificheremo tramite la direttiva using:

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
    try
    {
        Service.IserviceClient obj = new Service.IserviceClient();
        obj.DO1();

        obj.DO2();

        //throw new Exception("test new exception");

        ts.Complete();
    }
    catch (Exception ex)
    {
        ts.Dispose();
    }

}

Il metodo Complete eseguirà il commit della transazione; al contrario il metodo dispose eseguirà il rollback in caso di exception.