Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

CSharp:WCF

From Aino Wiki

Jump to: navigation, search

Definizione

Windows Communication Foundation (WCF) presente dalla versione 3.0 del .NET Framework, ha il principale scopo di rappresentare i modelli di comunicazione tra sistemi distribuiti. Per informazioni vedere: HTML.it
Era necessario unificare in un unico componente i metodi supportati da Microsoft per il trasporto di informazioni in ambienti distribuiti. WCF fornisce un meccanismo unitario per implementare: Web Services, Web Services Enhancementa (WSE), Remoting, Enterprise Services, MSMQ (Message Quequing).
Questo modello unificato di programmazione è basato sulle linee guida dell'architettura SOA.

Con WCF possiamo creare un semplice servizio ed esportarlo tramite IIS come un Web Service (basato sul protocollo HTTP) oppure utilizzabile col protocollo TCP/IP.

In Dettaglio

(da HTML.it) Un servizio è rappresentato da una classe detta appunto classe di servizio, compilata in un’assembly .NET, che per essere eseguita va “ospitata” in applicazioni che fungono da “host” per il servizio stesso.
Tali applicazioni possono essere IIS, WAS, servizi Windows o semplici eseguibili (quindi Windows Form, applicazioni WPF o console application).

WCF Host Application ex 01.png

L’applicazione host e i vari client (rispettivamente chi offre e chi consuma il servizio) parlano tra loro attraverso delle “terminazioni” dette Endpoint.

Struttura

Ogni servizio WCF è basato sul concetto di "service class" e "host application".

L’applicazione host e i vari client parlano tra loro con delle “terminazioni” dette Endpoint, un WCF è una collezione di EndPoint.

Ogni Endpoint è formato da tre componenti logiche, che rispondono ad altrettante domande (dove? come? cosa?):

  • Address (dove), è l'indirizzo al quale il servizio risponde. L'indirizzo è composto da un URI (indirizzo fisico del servizio), una "Identity" ed una lista di "Header".
  • Binding (come), sono le azioni intraprese per occuparsi del trasporto dell'informazione.
  • Contract (cosa), specifica l’elenco delle operazioni fornite dal servizio stesso (le API).
WCF f01.png
Esse permettono di definire le operazioni e i modi con cui le WCF vengono eseguite. Le caratteristiche di ogni singolo endpoint devono essere specificate nei file di configurazione dell’applicazione ospite (IIS ad esempio), sia nei file di configurazione dei client. Queste informazioni saranno inserite nella sezione <system.serviceModel>.

Per realizzare un client, dobbiamo creare una classe proxy che rappresenti la “service class” (lato client) esposta dal servizio WCF (lato server), per poi definire il suo Endpoint all’interno del file di configurazione (nel caso di un’applicazione ASP.NET quindi, all’interno del file web.config).

Hosting

Come intuito ci sono 2 tipologie di servizio:

  • WCF Service Application, per creare un servizio che DOVRA' essere hosted in IIS/WAS; questa tipologia implica l'uso del file *.svc.
  • WCF Service Library, per creare un servizio host-indipendent che è in ascolto su una determinata porta me che non necessita di IIS o altro host. Può esser tenuto in esecuzione dal tool WCF Service Host (wcfSrvHost.exe).

Hosting and consuming WCF
Fuori da Visual Studio:

WcfSvcHost.exe /service:WcfServiceLibrary1.dll /config:WcfServiceLibrary1.dll.config /client:"path/CustomClient.exe" /clientArg:"arguments that are passed to Client" 

Windows Service

Esempio di VS Solution con WCF e Servizio Windows:
...Aggiungere una semplice reference al progetto WCF, non una Service Reference...

WindowsService WCF 01.png

Codice del servizio creato:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
 
namespace WinService_PMSME
{
    public partial class Service1 : ServiceBase
    {
        ServiceHost m_objHosting;
        public Service1()
        {
            InitializeComponent();
        }
 
        protected override void OnStart(string[] args)
        {
            m_objHosting = new ServiceHost(typeof(Wcf_App_PMSME.PMSME_AService));
            m_objHosting.Open();
        }
 
        protected override void OnStop()
        {
            if (m_objHosting != null)
                m_objHosting.Close();
        }
    }
}

Installazione

Seguire la procedura per aggiungere l'installatore al servizio, dettagli qui. Il tutorial di Microsoft suggerisce che dopo aver selezionato 'serviceProcessInstaller1', nelle proprietà si imposti l'attributo "Account" a NetworkService ma non è detto.
Se si dovesse ricevere un errore "Access Denied" provare, dalle proprietà del servizio, a cambiare selezionando Local System account.
Installazione del Servizio (da VisualStudio: Tools\Command Line\Developer Command\Prompt):

C:\..\>installutil WinService_PMSME.exe

Disinstallazione:

C:\..\>installutil /u WinService_PMSME.exe

Progetto in VS

Configurazione

Service References

Configurazioni particolari, tipo indicare la porta del servizio etc, van fatti esplicitamente col tasto Dx del Mouse sulla specifica reference.

WCF configure service references.png

Infine configurare i parametri interessati

Service Reference Settings 4 Wiki.png

Test

WCF Test Client

Tool incluso in visual studio che dal file svc di un WCF consente di creare i DTO della Request e visualizzare la Response:

WCF Test Client.png

Esempi

Esempio 1 (Server Integrato VS)

Per esempio possiamo scegliere di creare una applicazione WCF Service Library, host-indipendent che non necessiti di IIS.

In questo esempio creeremo una solution (chiamata "Test_WCF_ClientServer") con:

  • un Progetto (Client) costituito da una Windows Application;
  • un Progetto (Server WCF) contenente gli EndPoint di servizio consumati nel progetto Client.

Progetto WCF

Creiamo prima il progetto con la Windows Application che fungerà da Client, la chiamerò "WcfServiceLibrary_Test".

SoluzioneEs WCF 01.png

Vengono creati automaticamente 2 files IService1.cs e Service1.cs

SoluzioneEs WCF 01.01.png

In dettaglio segue il codice generato automaticamente. Notare gli attributi [ServiceContract] della classe interfaccia (IService1) e [OperationContract] associata ai metodi previsti nell'interfaccia.

namespace WcfServiceLibrary_Test
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);
 
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
 
        // TODO: Add your service operations here
    }
 
 
 
    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";
 
        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }
 
        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

Service1.cs

namespace WcfServiceLibrary_Test
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
    public class Service1 : IService1
    {
        /// <summary>
        /// Esempio di implementazione di una chiamata a metodo con dato semplice 
        /// in input ed in output
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public string GetData(int value)
        {
            return string.Format("Hai digitato: {0}", value);
        }
 
        /// <summary>
        /// Esempio di implementazione di una chiamata a metodo con dato complesso 
        /// in input ed in output
        /// </summary>
        /// <param name="composite"></param>
        /// <returns></returns>
        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffisso";
            }
            return composite;
        }
    }
}

Ed il file di configurazione App.config come segue

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="WcfServiceLibrary_Test.Service1">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary_Test/Service1/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary_Test.IService1">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the value below to false before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="True" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
 
</configuration>

Progetto Client

SoluzioneEs WCF 022.png


Si aggiunge la "Service Reference..." nel progetto appena completato prima.

SoluzioneEs WCF 02.00.png


Per avere la seguente nuova Reference:

SoluzioneEs WCF 02.01.png

Contenuto del Form1.cs

using System;
using System.Windows.Forms;
using Test_WCF_ClientServer.ServiceReference1; // WCF
 
namespace Test_WCF_ClientServer
{
    public partial class Form1 : Form
    {
        private CompositeType m_ct = new CompositeType();
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                Service1Client srv = new Service1Client();
 
                CompositeType ct_Out = new CompositeType();
 
                m_ct = new CompositeType()
                {
                    BoolValue = ChkStringValue.Checked,
                    StringValue = " cicatost "
                };
 
 
                string outUno = srv.GetData(11);
                ct_Out = srv.GetDataUsingDataContract(m_ct);
 
                LblOutput_GetData.Text = outUno;
                LblOutput_GetDataUsingDataContract.Text = ct_Out.StringValue;
 
                MessageBox.Show("ok");
            }
            catch (Exception)
            {
 
                throw;
            }
            finally
            {
                // Impostazione del puntatore con la freccia di default
                Cursor.Current = Cursors.Default;
            }
        }
    }
}

app.config con l'aggiuta dei riferimenti al WCF "ServiceReferences"

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService1" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary_Test/Service1/"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
                contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

Esecuzione

Chiamando dal browser l'URI dell'endPoint

SoluzioneEs WCF 03.png

Particolare del Servizio del WCF esposto in automatico da VisualStudio

SoluzioneEs WCF 44.png

Esecuzione della applicazione Windows Form Client di test

SoluzioneEs WCF 05.png

Esempio 2 (Uso IIS)

Caso in cui il WCF è hostato su IIS

  • Progetto completo usando IIS per l'hosting nikpatel
  • Configurare WCF (VS 2012) hosting su IIS debugmode
  • Tutorial (VS 2008 fwk 3.5): wcftutorial (afferma però che IIS supporta solo protocollo HTTP ...)
  • Tutorial: c-sharpcorner

Problemi e soluzioni

Strumenti di trace

Tra i tools utili ad indagare sul contenuto dei messaggi inviati agli endpoint WCF c'è "service trace viewer" di Miscosoft, scaricabile da qui. I files avranno estensione *.svclog

Service References

References.CS vuoto

Nella configurazione va cambiato "REuse type in specific referenced assembly"

Service Reference Settings 4 Wiki.png

Mappa e Link


WEB API | C#


Visual Studio


Parole chiave:

Author