When using Silverlight 4 for Line of Business (LOB) applications, it is important to make use of WCF services for fetching and updating data to and from SL to WCF. WCF actively makes use of Representatial State Transfer (REST) and JavaScript Object Notation (JSON) for data communication. In my previous article ‘Performing DML Operations using WCF REST Service and Silverlight’, I have already explained REST with Silverlight. HTTP based services e.g. WCF also make use of JSON for data communication to and from client. The advantage of using JSON is that it can be directly instantiated in JavaScript without parsing. In the following article, I will be explain how to consuming WCF-JSON in Silverlight 4.0 application.
The Table Structure needed for this article (SQL Server 2008) is as below:
Creating WCF Service with JSON Request and Response Format
Step 1: Open VS2010 and create a blank solution. Name this solution as ‘SILV4_JSON_DML’. In this solution, add a WCF Service Application and name it ‘WCF_JSON-DML_Service’.
Step 2: Rename ‘IService1.cs’ to ‘IService.cs’ and write the following ServiceContract, OperationContract and DataContract.
C#
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "Employee"
)]
Employee[] GetAllEmployee();
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/CreateEmployee/{empNo}/{empName}/{salary}/{deptNo}",
Method = "POST")]
int InsertEmployee(string empNo, string empName, string salary, string deptNo);
}
[DataContract]
public class Employee
{
[DataMember]
public int EmpNo { get; set; }
[DataMember]
public string EmpName { get; set; }
[DataMember]
public int DeptNo { get; set; }
[DataMember]
public int Salary { get; set; }
}
VB.NET (Converted Code)
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.Text
Namespace WCF_JSON_DML_Service
<ServiceContract>
Public Interface IService
<OperationContract, WebGet(RequestFormat := WebMessageFormat.Json, ResponseFormat := WebMessageFormat.Json, BodyStyle := WebMessageBodyStyle.Bare, UriTemplate := "Employee")>
Function GetAllEmployee() As Employee()
<OperationContract, WebInvoke(RequestFormat := WebMessageFormat.Json, ResponseFormat := WebMessageFormat.Json, BodyStyle := WebMessageBodyStyle.Bare, UriTemplate := "/CreateEmployee/{empNo}/{empName}/{salary}/{deptNo}", Method := "POST")>
Function InsertEmployee(ByVal empNo As String, ByVal empName As String, ByVal salary As String, ByVal deptNo As String) As Integer
End Interface
<DataContract>
Public Class Employee
<DataMember>
Public Property EmpNo() As Integer
<DataMember>
Public Property EmpName() As String
<DataMember>
Public Property DeptNo() As Integer
<DataMember>
Public Property Salary() As Integer
End Class
End Namespace
Note that the ‘WebGet’ and ‘WebInvoke’ attributes are set to Request and Response format as JSON. The UriTemplate property will represent the string put in the Url instead of ‘GetAllEmployee’ method name.
Step 3: Rename ‘Service1.svc’ to ‘Service.svc’ and in the ‘Service’ class implement the ‘IService’ interface as shown elow:
C#
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace WCF_JSON_DML_Service
{
public class Service : IService
{
public Employee[] GetAllEmployee()
{
List<Employee> lstEmp = new List<Employee>();
SqlConnection Conn = new SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI");
Conn.Open();
SqlCommand Cmd = new SqlCommand("Select * from Employee", Conn);
SqlDataReader Reader = Cmd.ExecuteReader();
while (Reader.Read())
{
lstEmp.Add(new Employee()
{
EmpNo = Convert.ToInt32(Reader["EmpNo"]),
EmpName = Reader["EmpName"].ToString(),
DeptNo = Convert.ToInt32(Reader["DeptNo"]),
Salary = Convert.ToInt32(Reader["Salary"])
});
}
Reader.Close();
Conn.Close();
return lstEmp.ToArray();
}
public int InsertEmployee(string empNo, string empName, string salary, string deptNo)
{
int Inserterd = 0;
SqlConnection Conn = new SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI");
Conn.Open();
SqlCommand Cmd = new SqlCommand();
Cmd.Connection = Conn;
Cmd.CommandText = "Insert into Employee Values(@EmpNo,@EmpName,@Salary,@DeptNo)";
Cmd.Parameters.AddWithValue("@EmpNo", Convert.ToInt32(empNo));
Cmd.Parameters.AddWithValue("@EmpName", empName);
Cmd.Parameters.AddWithValue("@Salary", Convert.ToInt32(salary));
Cmd.Parameters.AddWithValue("@DeptNo", Convert.ToInt32(deptNo));
Inserterd = Cmd.ExecuteNonQuery();
Conn.Close();
return Inserterd;
}
}
}
VB.NET (Converted Code)
Imports System
Imports System.Collections.Generic
Imports System.Data.SqlClient
Namespace WCF_JSON_DML_Service
Public Class Service
Implements IService
Public Function GetAllEmployee() As Employee()
Dim lstEmp As New List(Of Employee)()
Dim Conn As New SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI")
Conn.Open()
Dim Cmd As New SqlCommand("Select * from Employee", Conn)
Dim Reader As SqlDataReader = Cmd.ExecuteReader()
Do While Reader.Read()
lstEmp.Add(New Employee() With {.EmpNo = Convert.ToInt32(Reader("EmpNo")), .EmpName = Reader("EmpName").ToString(), .DeptNo = Convert.ToInt32(Reader("DeptNo")), .Salary = Convert.ToInt32(Reader("Salary"))})
Loop
Reader.Close()
Conn.Close()
Return lstEmp.ToArray()
End Function
Public Function InsertEmployee(ByVal empNo As String, ByVal empName As String, ByVal salary As String, ByVal deptNo As String) As Integer
Dim Inserterd As Integer = 0
Dim Conn As New SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI")
Conn.Open()
Dim Cmd As New SqlCommand()
Cmd.Connection = Conn
Cmd.CommandText = "Insert into Employee Values(@EmpNo,@EmpName,@Salary,@DeptNo)"
Cmd.Parameters.AddWithValue("@EmpNo", Convert.ToInt32(empNo))
Cmd.Parameters.AddWithValue("@EmpName", empName)
Cmd.Parameters.AddWithValue("@Salary", Convert.ToInt32(salary))
Cmd.Parameters.AddWithValue("@DeptNo", Convert.ToInt32(deptNo))
Inserterd = Cmd.ExecuteNonQuery()
Conn.Close()
Return Inserterd
End Function
End Class
End Namespace
The above code connects to the Database server and performs the GetAll and Create (insert) operation.
Step 4: Make the following modification in the ‘Service.svc’ file:
<%@ ServiceHost Language="C#" Debug="true" Service="WCF_JSON_DML_Service.Service" CodeBehind="Service.svc.cs" %>
Step 5: Open the Web.Config file and make the following changes in <System.ServiceModel> tag:
<system.serviceModel>
<services>
<service name="WCF_JSON_DML_Service.Service" behaviorConfiguration="ServBehave">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="EdpBehave"
contract="WCF_JSON_DML_Service.IService"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="EdpBehave">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServBehave">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
The binding used is ‘webHttpBinding’ which is used to configure endpoints for WCF REST and JSON services that are exposed through HTTP instead of SOAP. The ‘EndpointBehavior’ ‘<webHttp/> for the response and request format is applied on the OperationContract in ‘IService’ interface for JSON communication.
Step 6: Publish the WCF service on IIS and browse the ‘Service.svc’ file as below with Url for the method ‘GetAllEmployee’:
Press enter and it will download the file containing JSON response:
Now save the file on disk and open it with notepad the result will be as shown below:
So this creates a WCF JSON service hosted in IIS!
Creating Silverlight 4.0 client application to consume the JSON response
Now we will create a SL4 client, which will be consuming JSON Response from the WCF service.
Step 1: In the same solution add a new SL4 project and name it as ‘SILV_JOSN_DML_Client’.
Step 2: Open MainPage.xaml and design it as shown below:
<Grid x:Name="LayoutRoot" Background="White" Height="480" Width="796">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="388*" />
<ColumnDefinition Width="408*" />
</Grid.ColumnDefinitions>
<sdk:DataGrid AutoGenerateColumns="True" Height="255" HorizontalAlignment="Left" Margin="23,127,0,0" Name="dgEmp" VerticalAlignment="Top" Width="337" />
<Button Content="Get Available Employees" Height="48" HorizontalAlignment="Left" Margin="22,400,0,0" Name="btnGetAllEmployee" VerticalAlignment="Top" Width="340" Click="btnGetAllEmployee_Click" />
<TextBlock Height="92" HorizontalAlignment="Left" Margin="26,20,0,0" Name="textBlock1" Text="Available Employees" VerticalAlignment="Top" Width="326" TextAlignment="Center" FontSize="28" FontWeight="ExtraBold" />
<Grid Grid.Column="1" Height="276" HorizontalAlignment="Left" Margin="25,125,0,0" Name="grid1" VerticalAlignment="Top" Width="345">
<Grid.RowDefinitions>
<RowDefinition Height="51*" />
<RowDefinition Height="49*" />
<RowDefinition Height="47*" />
<RowDefinition Height="45*" />
<RowDefinition Height="84*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="165*" />
<ColumnDefinition Width="180*" />
</Grid.ColumnDefinitions>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,16,0,0" Name="textBlock3" Text="Employee No:" VerticalAlignment="Top" Width="129" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,11,0,0" Name="textBlock4" Text="Employee Name:" VerticalAlignment="Top" Width="129" Grid.Row="1" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBlock5" Text="Salary" VerticalAlignment="Top" Width="129" Grid.Row="2" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,12,0,0" Name="textBlock6" Text="Department No:" VerticalAlignment="Top" Width="129" Grid.Row="3" />
<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Left" Margin="22,16,0,0" Name="txteno" VerticalAlignment="Top" Width="141" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="22,7,0,0" Name="txtename" VerticalAlignment="Top" Width="141" Grid.Column="1" Grid.Row="1" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="22,10,0,0" Name="txtsal" VerticalAlignment="Top" Width="141" Grid.Column="1" Grid.Row="2" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="22,12,0,0" Name="txtdno" VerticalAlignment="Top" Width="141" Grid.Column="1" Grid.Row="3" />
<Button Content="Insert" Grid.Column="1" Grid.Row="4" Height="42" HorizontalAlignment="Left" Margin="22,13,0,0" Name="btnInsert" VerticalAlignment="Top" Width="141" Click="btnInsert_Click" />
</Grid>
<TextBlock Height="92" HorizontalAlignment="Left" Margin="35,20,0,0" Name="textBlock2" Text="Register New Employee" VerticalAlignment="Top" Width="326" Grid.Column="1" TextAlignment="Center" FontSize="28" TextWrapping="Wrap" FontWeight="ExtraBold" />
</Grid>
The Design will be as given below:
Step 3: Now to consume the JSON response from WCF and deserialize it into an object, we need to add the following references in our Silverlight application.
The reference are to System.Runtime.Serialization.dll and System.ServiceModel.web.dll from the Silverlight installed folder.
Step 4: In the SL project, add the Employee class. This will be used to store, deserialized data from the JSON.
C#
public class Employee
{
public int EmpNo { get; set; }
public string EmpName { get; set; }
public int DeptNo { get; set; }
public int Salary { get; set; }
}
VB.NET (Converted Code)
Public Class Employee
Public Property EmpNo() As Integer
Public Property EmpName() As String
Public Property DeptNo() As Integer
Public Property Salary() As Integer
End Class
Step 5: Open MainPage.Xaml.cs/vb and write the following ‘RequestEmployee()’ method. This will use the ‘WebClient’ class to make call to the WCF service using Url. The call made will be asynchronous. Call the method in ‘Get Available Employees’ button click as shown below:
C#
private void btnGetAllEmployee_Click(object sender, RoutedEventArgs e)
{
RequestEmployees();
}
private void RequestEmployees()
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri("http://localhost:8900/JOSN_DML_VD/Service.svc/Employee"));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try
{
if (e.Result != null)
{
Stream jsonStream = e.Result;
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<Employee>));
List<Employee> objEmployeeData = (List<Employee>)ser.ReadObject(jsonStream);
dgEmp.ItemsSource = objEmployeeData;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
VB.NET (Converted Code)
Private Sub btnGetAllEmployee_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
RequestEmployees()
End Sub
Private Sub RequestEmployees()
Dim wc As New WebClient()
AddHandler wc.OpenReadCompleted, AddressOf wc_OpenReadCompleted
wc.OpenReadAsync(New Uri("http://localhost:8900/JOSN_DML_VD/Service.svc/Employee"))
End Sub
Private Sub wc_OpenReadCompleted(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs)
Try
If e.Result IsNot Nothing Then
Dim jsonStream As Stream = e.Result
Dim ser As New DataContractJsonSerializer(GetType(List(Of Employee)))
Dim objEmployeeData As List(Of Employee) = CType(ser.ReadObject(jsonStream), List(Of Employee))
dgEmp.ItemsSource = objEmployeeData
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
The above code reads the stream which contains JSON data and using ‘DataContractJsonSerializer’, the stream is stored in the List<Employee> object.
Step 6: Run the application and click on the ‘Get Available Employees’ button. The following result will be displayed:
In the next task, we will see a demo of an Insert operation from SL4 application using JSON service.
Insert Data From a Silverlight application using JSON service
Step 7: In the MainPage.Xaml.cs/vb write the following methods in ‘Insert’ button click:
C#
void CallBackJSONAddRequest(IAsyncResult ar)
{
//Contains information of the Async object containing Request Information
WebRequest req = (WebRequest)ar.AsyncState;
//Returns stream for writing data to the Web Resource
Stream reqStream = req.EndGetRequestStream(ar);
reqStream.Close();
//Now Collect the response Asynchronously
req.BeginGetResponse(CallBackJSONResponse, req);
}
//Response Callback, is mandatory to complete operations on the receiving end
void CallBackJSONResponse(IAsyncResult ar)
{
try
{
WebRequest req = (WebRequest)ar.AsyncState;
//Collect the reponse
WebResponse res = req.EndGetResponse(ar);
Stream strResult = res.GetResponseStream();
strResult.Close();
res.Close();
}
catch (Exception ex)
{
string s = ex.Message;
}
}
private void btnInsert_Click(object sender, RoutedEventArgs e)
{
try
{
string uploadUrl = "http://localhost:8900/JOSN_DML_VD/Service.svc/CreateEmployee/" + txteno.Text + "/" + txtename.Text + "/" + txtsal.Text + "/" + txtdno.Text;
WebRequest addRequest = WebRequest.Create(uploadUrl);
addRequest.Method = "POST";
//Begin the Asynchrnous Request
addRequest.BeginGetRequestStream(CallBackJSONAddRequest, addRequest);
MessageBox.Show("Insert Completed");
RequestEmployees();
}
catch (Exception ex)
{
HtmlPage.Window.Alert(ex.Message);
}
}
VB.NET (Converted Code)
Private Sub CallBackJSONAddRequest(ByVal ar As IAsyncResult)
'Contains information of the Async object containing Request Information
Dim req As WebRequest = CType(ar.AsyncState, WebRequest)
'Returns stream for writing data to the Web Resource
Dim reqStream As Stream = req.EndGetRequestStream(ar)
reqStream.Close()
'Now Collect the response Asynchronously
req.BeginGetResponse(AddressOf CallBackJSONResponse, req)
End Sub
'Response Callback, is mandatory to complete operations on the receiving end
Private Sub CallBackJSONResponse(ByVal ar As IAsyncResult)
Try
Dim req As WebRequest = CType(ar.AsyncState, WebRequest)
'Collect the reponse
Dim res As WebResponse = req.EndGetResponse(ar)
Dim strResult As Stream = res.GetResponseStream()
strResult.Close()
res.Close()
Catch ex As Exception
Dim s As String = ex.Message
End Try
End Sub
Private Sub btnInsert_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Try
Dim uploadUrl As String = "http://localhost:8900/JOSN_DML_VD/Service.svc/CreateEmployee/" & txteno.Text & "/" & txtename.Text & "/" & txtsal.Text & "/" & txtdno.Text
Dim addRequest As WebRequest = WebRequest.Create(uploadUrl)
addRequest.Method = "POST"
'Begin the Asynchrnous Request
addRequest.BeginGetRequestStream(AddressOf CallBackJSONAddRequest, addRequest)
MessageBox.Show("Insert Completed")
RequestEmployees()
Catch ex As Exception
HtmlPage.Window.Alert(ex.Message)
End Try
End Sub
In the above code the ‘Insert’ button click code makes use of the ‘WebRequest’ class to make an async POST operation to the ‘CreateEmployee’ method, with the paramater in the Url. This generates an async request stream. The method ‘CallBackJSONAddRequest’ contains information about the async request object containing the request information. Once the request is completed, this method collect the response asynchronously. The method ‘CallBackJSONResponse’ completed the reponse operation and puts the result into the stream.
Step 8: Run the application, enter the data in textboxes and click on the ‘Insert’ button. The following result will be displayed:
The same insert logic mechanism for Async Request and Async Response can be used for Update and Delete operations.
Concusion:
WCF JSON provideds a nice mechanism to handle Http Communication from Silverlight instead of using SOAP. JSON is the most suitable mechanism for data exchange.
The entire source code of this article can be downloaded over here
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions), and Front-end technologies like Angular and React. Follow him on twitter @
maheshdotnet or connect with him on
LinkedIn