Per iniziare dobbiamo creare una nuova
soluzione in Visual Studio (il presente esempio è stato creato con Visual
Studio 2010), con nome ServiceApp e ti tipo Windows Forms Application.
Quindi aggiungiamo un nuovo progetto sempre di tipo Windows Forms Application
ma con nome ClientApp.
Nel progetto ServiceApp aggiungiamo un
nuovo file di tipo “Application Configuration File” e con nome
App.config, una classe con nome Service1 e un’interfaccia
IService1.
Il file App.config viene utilizzato per
configurare il servizio WCF, è possibile configurare i servizi WCF anche
mediante programmazione ma la configurazione attraverso file presenta vantaggi
in termini di flessibilità, manutenzione e configurazione ad applicazione
ultimata.
Al progetto ServiceApp deveno essere
aggiunti i riferimenti agli assembly:
·
System.ServiceModel.dll;
·
System.ServiceModel.Web.dll;
·
System.Runtime.Serialization.dll;
Al progetto ClientApp devono essere
aggiunti i riferimenti agli assembly:
·
System.ServiceModel.dll;
·
System.Runtime.Serialization.dll;
Nel progetto ClientApp deve anche essere
aggiunto un riferimento al progetto ServiceApp
Il risultato finale è qualcosa del
tipo:
All’interno del file IService1.cs
è presente il contratto entro cui chi vuole comunicare con il servizio si
deve attenere:
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
namespace
WcfRestJsonExample
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate =
"/GetData", RequestFormat = WebMessageFormat.Json, ResponseFormat =
WebMessageFormat.Json)]
string GetData();
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate =
"/CompositeType?boolValue={boolValue}&stringValue={stringValue}",
RequestFormat = WebMessageFormat.Json, ResponseFormat =
WebMessageFormat.Json)]
CompositeType GetCompositeType(Boolean boolValue,
String stringValue);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate =
"/CompositeType", RequestFormat = WebMessageFormat.Json, ResponseFormat
= WebMessageFormat.Json)]
bool SaveCompositeType(CompositeType
compositeType);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate =
"/UploadFile", RequestFormat = WebMessageFormat.Json, ResponseFormat =
WebMessageFormat.Json)]
int UploadData(FileData fileInfo);
}
[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; }
}
public override string ToString()
{
return String.Format("CompositeType:
BoolValue={0}; StringValue={1}", BoolValue, StringValue);
}
}
[DataContract]
public class FileData
{
[DataMember]
public
string Name
{
get;
set;
}
[DataMember]
public
byte[] Content
{
get;
set;
}
}
}
|
Il file Service1.cs contiene
l’implementazione dell’interfaccia IService1.cs che definisce il
contratto del servizio WCF:
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfRestJsonExample
{
[ServiceBehavior(InstanceContextMode =
InstanceContextMode.Single, ConcurrencyMode =
ConcurrencyMode.Multiple)]
public class Service1 : IService1
{
public string GetData()
{
return DateTime.Now.ToString();
}
public CompositeType GetCompositeType(Boolean
boolValue, String stringValue)
{
return new CompositeType() {
BoolValue = boolValue, StringValue = stringValue };
}
public bool SaveCompositeType(CompositeType
compositeType)
{
System.Diagnostics.Trace.WriteLine(compositeType);
return true;
}
public int UploadData(FileData fileInfo)
{
return fileInfo.Content.Length;
}
}
}
|
Nel file App.config dobbiamo inserire i
parametri di configurazione del servizio:
<system.web>
</system.web>
<system.servicemodel>
bypassProxyOnLocal="true"
useDefaultWebProxy="false"
hostNameComparisonMode="WeakWildcard"
sendTimeout="10:15:00"
openTimeout="10:15:00"
receiveTimeout="10:15:00"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="StreamedRequest">
maxStringContentLength="2147483647" />
</system.servicemodel>
<system.servicemodel></system.servicemodel>
|
Infine dobbiamo ospitare il servizio,
visto che abbiamo scelto un progetto di tipo Windows Forms Application per il
progetto ServiceApp, possiamo inserire creare l’istanza e
l’apertura del servizio sull‘evento di OnLoad della finestra
principale dell’applicazione ServiceApp:
using
System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
namespace ServiceApp
{
public class Form1 : Form
{
private ServiceHost m_serviceHost;
private WcfRestJsonExample.IService1
m_service1;
///
/// Required designer variable.
///
private System.ComponentModel.IContainer
components = null;
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
m_service1 = new
WcfRestJsonExample.Service1();
m_serviceHost = new
ServiceHost(m_service1);
m_serviceHost.Open();
}
///
/// Clean up any resources being used.
///
///
true if
managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
if (disposing && (components
!= null))
{
m_serviceHost.Close();
m_service1 = null;
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not
modify
/// the contents of this method with the code
editor.
///
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new
System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new
System.Drawing.Size(284, 262);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
}
} |
A questo punto possiamo passare al progetto
ClientApp che ha il compito di invocare il metodi del servizio pubblicati
attraverso il contratto WCF.
Il servizio presenta un metodo invocabile
attraverso un comando HTTP di tipo GET con la seguente firma:
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate =
"/CompositeType?boolValue={boolValue}&stringValue={stringValue}",
RequestFormat = WebMessageFormat.Json, ResponseFormat =
WebMessageFormat.Json)]
CompositeType GetCompositeType(Boolean boolValue, String
stringValue);
|
Se vogliamo richiamare il metodo
sopraindicato con un commando HTTP di tipo GET dobbiamo utilizzare un oggetto
WebClient:
WebClient client =
new WebClient();
byte[]
data = client.DownloadData(URL_ROOT +
"CompositeType?boolValue=true&stringValue=get_object_to_test");
Stream
stream = new MemoryStream(data);
DataContractJsonSerializer obj = new
DataContractJsonSerializer(typeof(CompositeType));
CompositeType result = obj.ReadObject(stream) as
CompositeType;
|
Se vogliamo invece invocare un comando HTTP
di tipo POST, dobbiamo possiamo utilizzare il metodo del servizio che presenta
la seguente firma:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/CompositeType",
RequestFormat = WebMessageFormat.Json, ResponseFormat =
WebMessageFormat.Json)]
bool SaveCompositeType(CompositeType compositeType);
|
Invocabile attraverso l’oggetto
WebClient nel seguente modo:
WebClient client
= new WebClient();
client.Headers["Content-type"] = "application/json";
FileData fileInfo = new FileData();
fileInfo.Name = "Test.txt";
fileInfo.Content = Get1MBFile();
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer serializer = new
DataContractJsonSerializer(typeof(FileData));
serializer.WriteObject(stream, fileInfo);
byte[] data = client.UploadData(URL_ROOT + "UploadFile", "POST",
stream.ToArray());
stream = new MemoryStream(data);
serializer = new DataContractJsonSerializer(typeof(int));
int result = (int)serializer.ReadObject(stream);
|