Creare un servizio WCF che ritorna dati in JSON
Per creare un servizio WCF che ritorna dati in JSON si parte da un progetto Visual Studio 2010/2012 di tipo WebApplicatione e si aggiunge un WCF. A questo punto devi modificare i 3 file aggiunti più il web.config.
I 3 file sono:
Nell'esempio si vede sia una chiamata in GET (GetJson) che una in POST (SommaDati). La chiamata GET è caratterizzata dalla decorazione WebGet e dalla proprietà BodyStyle impostata a WebMessageBodyStyle.Bare. Nel caso di POST la decorazione diventa WebInvoke e la proprietà BodyStyle è impostata a WebMessageBodyStyle.WrappedRequest e viene aggiunto la proprietà RequestFormat=WebMessageFormat.Json.
Nota il parametro UriTemplate che ridefinisce la url di chiamata del metodo, in questo caso diventa /Rest.svc/Json/valoreDaPassare e /Rest.svc/PostData. Inoltre nel caso del paramtro GET posso mappare i parametri tramite le parentesi graffe.
Va poi modificato il web.config per configurare il servizio WCF
C'è poi una classe di supporto che definisce un extension method per gestire la conversione delle date in formato JavaScript
Il tutto può essere testato con questa pagina html
I 3 file sono:
- IRest.cs: che definisce l'interfaccia di comunicazione
- Rest.svc: il servizio WCF
- Rest.svc.cs: il code behind del servizio WCF che implementa l'interfaccia IRest
Nell'esempio si vede sia una chiamata in GET (GetJson) che una in POST (SommaDati). La chiamata GET è caratterizzata dalla decorazione WebGet e dalla proprietà BodyStyle impostata a WebMessageBodyStyle.Bare. Nel caso di POST la decorazione diventa WebInvoke e la proprietà BodyStyle è impostata a WebMessageBodyStyle.WrappedRequest e viene aggiunto la proprietà RequestFormat=WebMessageFormat.Json.
C#: IRest.cs
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace Sgart.WCF.Json
{
[ServiceContract]
public interface IRest
{
[OperationContract]
[WebGet(UriTemplate = "Json/{param}"
, BodyStyle = WebMessageBodyStyle.Bare
, ResponseFormat = WebMessageFormat.Json)]
List<object> GetJson(string param);
[OperationContract]
[WebInvoke(UriTemplate = "PostData"
, BodyStyle = WebMessageBodyStyle.WrappedRequest
, RequestFormat = WebMessageFormat.Json
, ResponseFormat = WebMessageFormat.Json)]
double SommaDati(double v1, double v2);
}
}
HTML: Rest.svc
<%@ ServiceHost Language="C#" Debug="true" Service="Sgart.WCF.Json.Rest"
CodeBehind="Rest.svc.cs" %>
C#: Rest.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SgartIt.Extensions;
namespace Sgart.WCF.Json
{
public class Rest : IRest
{
public List<object> GetJson(string param)
{
//ritorno dei dati fittizzi di test
List<object> result = new List<object>();
for (int i = 0; i < 10; i++)
{
result.Add(new object[] { DateTime.Now.ToJavaScript(), i, param });
}
return result;
}
public double SommaDati(double v1, double v2)
{
return Math.Round(v1 + v2, 6);
}
}
}
Va poi modificato il web.config per configurare il servizio WCF
XML: web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="sgartHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="Sgart.WCF.Json.Rest">
<endpoint address=""
behaviorConfiguration="sgartHttpBehavior"
binding="webHttpBinding"
contract="Sgart.WCF.Json.IRest" >
</endpoint>
</service>
</services>
</system.serviceModel>
</configuration>
C'è poi una classe di supporto che definisce un extension method per gestire la conversione delle date in formato JavaScript
C#: SgartIt.Extensions.cs
using System;
namespace SgartIt.Extensions
{
public static class DateTimeJavaScript
{
private static readonly long minTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
public static long ToJavaScript(this DateTime dt)
{
return (long)((dt.ToUniversalTime().Ticks - minTicks) / 10000);
}
}
}
Il tutto può essere testato con questa pagina html
HTML: default.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Test WCF Json - Sgart.it</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<div id="container-get"></div>
<div id="container-post"></div>
<script type="text/javascript">
$(function () {
//chiamata GET
var param = "prova";
$.getJSON('/Rest.svc/Json/' + param, function (data) {
var s = "<ul>";
for (var i = 0; i < data.length; i++) {
var item = data[i];
s += "<li>Data:" + (new Date(item[0])) + ", Id:" + item[1] + ", Param:" + item[2] + "</li>";
}
$("#container-get").html(s);
});
//chiamata POST
var postData = { v1: 1.33, v2: 4.44 };
$.ajax({
type: "POST",
url: '/Rest.svc/PostData',
data: JSON.stringify(postData),
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data, textStatus, qXHR) {
$("#container-post").html("La somma di v1:'" + postData.v1 + "' e v2:'" + postData.v2 + "' da come risultato " + data);
},
error: function (jqXHR, textStatus, errorThrown) {
alert("error:" + textStatus + " - " + errorThrown);
}
});
});
</script>
</body>
</html>