Menus

Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Sunday, January 27, 2013

Three ways to do WCF instance management

Introduction

Very often we would like to control the way WCF service objects are instantiated on a WCF server. You would want to control how long the WCF instances should be residing on the server.
The WCF framework has provided three ways by which we can control WCF instance creation. In this article, we will first try to understand those three ways of WCF service instance control with simple code samples of how to achieve them. Finally, we will compare when to use them and under what situations.

WCF service object instancing basics

In normal WCF request and response communication, the following sequence of actions takes place:
  • WCF client makes a request to a WCF service object.
  • WCF service object is instantiated.
  • WCF service instance serves the request and sends the response to the WCF client.
Following is a pictorial representation of how WCF requests and responses work.

Following are different ways by which you can create WCF instances:
  • Create a new WCF service instance on every WCF client method call.
  • Only one WCF service instance should be created for every WCF client session.
  • Only one global WCF service instance should be created for all WCF clients.
To meet the above scenarios, WCF has provided three ways by which you can control WCF service instances:
  • Per call
  • Per session
  • Single instance

Per call instance mode

When we configure a WCF service as per call, new service instances are created for every method call you make via a WCF proxy client. The image below shows this in a pictorial format:
  • The WCF client makes the first method call (method call 1).
  • A new WCF service instance is created on the server for this method call.
  • The WCF service serves the request and sends the response and the WCF instance is destroyed and given to the garbage collector for clean up.
  • Now let’s say the WCF client makes a second method call, a new instance is created, the request is served, and the WCF instance is destroyed.
In other words, for every WCF client method call, a WCF service instance is created, and destroyed once the request is served.

How to implement WCF per call instancing

In order to specify the instancing mode, we need to provide the InstanceContextMode value in the ServiceBehavior attribute as shown below. This attribute needs to specified on the Service class. In the below code snippet, we have specified intCounter as a class level variable and the class counter is incremented by one when the Increment method is called.
 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Percall)] 
public class Service : IService
{
    private int intCounter;

    public int Increment()
    {
        intCounter++
        return intCounter;
    }
}

At the client, we consume the WCF client and we call the Increment method twice.
ServiceReference1.ServiceClient obj = new ServiceReference1.ServiceClient(); 
MessageBox.Show(obj.Increment().ToString());
MessageBox.Show(obj.Increment().ToString());
Even though we have called the Increment method twice, we get the value ‘1’. In other words, the WCF service instance is created for every method call made to the WCF service instance so the value will always be one.

Per session instance mode

Very often we need to maintain state between method calls or for a particular session. For those kinds of scenarios, we will need to configure the service per session. In per session, only one instance of a WCF service object is created for a session interaction. The figure below explains this in pictorial format.
  • The client creates the proxy of the WCF service and makes method calls.
  • A WCF service instance is created which serves the method response.
  • The client makes one more method call in the same session.
  • The same WCF service instance serves the method call.
  • When the client finishes its activity, the WCF instance is destroyed and served to the garbage collector for clean up.

How to implement per session instancing

To configure service as per session, we need to configure the ServiceBehavior attribute with a PerSession value in the InstanceContextMode object.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
public class Service : IService
{
    private int intCounter;
    public int Increment()
    {
        intCounter++
        return intCounter;
    }
}
At the client side, when we run the below client code, you should see the value ‘2’ after the final client code is executed. We have called the method twice so the value will be seen as two.
 
ServiceReference1.ServiceClient obj = new ServiceReference1.ServiceClient(); 
MessageBox.Show(obj.Increment().ToString());
MessageBox.Show(obj.Increment().ToString());

Single instance mode

Often we would like to create one global WCF instance for all WCF clients. To create a single instance of a WCF service, we need to configure the WCF service as Single instance mode. Below is a simple pictorial notation of how the single instance mode will operate:
  • WCF client 1 requests a method call on the WCF service.
  • A WCF service instance is created and the request is served. The WCF service instance is not destroyed, the service instance is persisted to server other requests.
  • Now let’s say some other WCF client, e.g., client 2, requests a method call.
  • The same WCF instance which was created by WCF client 1 is used to serve the request for WCF client 2. In other words, only one global WCF server service instance is created to serve all client requests.

How to implement single instance mode

In order to create a single instance of a WCF service, we need to specify InstanceContextMode as Single.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class Service : IService
{
}
 
If you call the WCF service from a different client, you will see the counter incrementing. The counter becomes a global variable.

When should you use per call, per session, and single mode?

Per call

  • You want a stateless services.
  • Your service holds intensive resources like connection objects and huge memory objects.
  • Scalability is a prime requirement. You would like to have a scaled out architecture.
  • Your WCF functions are called in a single threaded model.

Per session

  • You want to maintain states between WCF calls.
  • You a scaled up architecture.
  • Light resource references.

Single

  • You want share global data through your WCF service.
  • Scalability is not a concern.

WCF Concurrency (Single, Multiple, and Reentrant) and Throttling

Introduction and goal

In this article, we will concentrate on WCF concurrency and throttling. We will first try to understand what is WCF concurrency and the three important types of WCF concurrency. We will then see a small sample of WCF concurrency with Single and Multiple. We will then go through 9 combinations of WCF concurrency and instancing. Finally we will try to understand how to configure throttling using the WCFweb.config’ file.

Why do we need concurrency in WCF?

If you search on the web for the dictionary meaning of concurrency, you will find the following definition:
Happening at the same time
WCF concurrency helps us configure how WCF service instances can serve multiple requests at the same time. You will need WCF concurrency for the below prime reasons; there can be other reasons as well but these stand out as important reasons:
  • Increase throughput: Many times you want to increase the amount of work your WCF service instance does at any moment of time. In other words, you would like to increase the throughput. Throughput means how much work a given thing can do.
  • By default, a WCF service handles only one request at a given moment of time.
  • Integration with a legacy system: Many times your WCF services interact with legacy systems like VB6, COM, etc. It’s very much possible that these systems are not multithreaded, in other words they handle only one request at any given time. So even though your WCF service has concurrent capabilities, you would still like to handle one request at a time. This is achieved by using throttling in combination with WCF concurrency capabilities.

WCF concurrency and instancing – Two different things

WCF instancing and WCF concurrency are two different things. WCF instance dictates how objects are created while WCF concurrency dictates how many requests can be handled by WCF objects.
I do understand that many of our developer friends know this difference, but as you go deeper into WCF concurrency, there is lot of connection with WCF instancing also, so I wanted to just emphasize the differences.
WCF instancing gives three levels of WCF object instance controls: per call, per session, and single. In similar lines, WCF also has three ways of implementing WCF concurrency.

Three types of WCF concurrency

There are three ways by which you can handle concurrency in WCF: single, multiple, and reentrant. To specify WCF concurrency, we need to use the ServiceBehavior tag as shown below, with the appropriate ‘ConCurrencyMode’ property value.

Single: A single request has access to the WCF service object at a given moment of time. So only one request will be processed at any given moment of time. The other requests have to wait until the request processed by the WCF service is completed.
Multiple: In this scenario, multiple requests can be handled by the WCF service object at any given moment of time. In other words, requests are processed at the same time by spawning multiple threads on the WCF server object. So you have great throughput here but you need to ensure concurrency issues related to WCF server objects.
Reentrant: A single request thread has access to the WCF service object, but the thread can exit the WCF service to call another WCF service or can also call a WCF client through callback and reenter without deadlock.

Sample code demonstration

In order to demonstrate this, let’s create a simple sample code as shown below. We will create a simple WCF service with a method name Call. When a client calls this WCF service, it will display the following details:
  • Client name that made the call. This value will be provided as an input when the client wants to make a call to the WCF service.
  • Instance number, this will represent the number of WCF instances which are serving the request.
  • Thread number which is executing the method.
  • Time when the Call method was actually called.
Below is the service contract of the Call method. Please note that OperationContract is defined with IsOneWay as true.

[ServiceContract]
public interface IHelloWorldService
{
    [OperationContract(IsOneWay=true)]
    void Call(string ClientName);
}
 
Below is a simple implementation of the service contract IHelloWorldService interface. It has an instance variable i which helps us maintain the instance counter and a simple Console.Writeline which displays the client name, instance number, thread number, and time when the method was called.
This method waits for 5 seconds using the ‘Thread.Sleep’ function.
 
public class HelloWorldService : IHelloWorldService
{
    // maintain instance count 
    public int i;
    public void Call(string ClientName)
    {
        // increment instance counts
        i++;




        // display client name, instance number , thread number and time when 
        // the method was called




        Console.WriteLine("Client name :" + ClientName + " Instance:" + 
          i.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + 
          " Time:" + DateTime.Now.ToString() + "\n\n");




        // Wait for 5 seconds
        Thread.Sleep(5000);
    }
}
 
This WCF service will be self hosted using WsHttpBinding as shown below. We have chosen 
self hosting so that we can monitor the time, threads, 
and number of instances of the WCF service.
 
static void Main(string[] args)
{
    //Create a URI to serve as the base address
    Uri httpUrl = new Uri("http://localhost:8010/MyService/HelloWorld");




    //Create ServiceHost
    ServiceHost host = new ServiceHost(typeof(ClassLibrary1.HelloWorldService), httpUrl); 




    //Add a service endpoint
    host.AddServiceEndpoint(typeof(ClassLibrary1.IHelloWorldService), new WSHttpBinding(), "");




    //Enable metadata exchange
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    host.Description.Behaviors.Add(smb);




    //Start the Service
    host.Open();




    Console.WriteLine("Service is host at " + DateTime.Now.ToString());
    Console.WriteLine("Host is running... Press <Enter> key to stop");
    Console.ReadLine();
}
 
From the client side, we will make five continuous calls simultaneously on the WCF service.
Below is the code snippet for this:
 
Console.WriteLine("Enter Client name");
string str = Console.ReadLine();
ServiceReference1.HelloWorldServiceClient obj = 
             new ServiceReference1.HelloWorldServiceClient();




for(int i=0;i<5;i++)
{
    obj.Call(str);
}
If you run the above project and monitor your WCF server service, you will see the screenshot. There are two important points to note:
  • By default the WCF service is configured to run with per call. So new instances are created every time the service runs. Instance 1 indicates new instances created for every method call.
  • By default the concurrency is single so the same thread is used to service all five requests which are sent from the WCF client side. You can see the value of the thread is always 4.
  • The most important factor is time. As concurrency is configured as single, it will be called one after another sequentially. You can notice this from the time difference of method calls of 5 seconds.

Let’s go and change the concurrency mode to multiple. In order to change the concurrency mode to multiple, we need to specify Multiple as the concurrency mode as shown in the below code snippet.

If you run the client now, you can see different threads (i.e., thread 4, 5, 6, 7, and 8) are spawned to serve the request and the time of the method calls are almost same. In other words, the methods are executed concurrently on different threads.
In short, you are now having a higher throughput in less amount of time.

9 combinations of Instancing and Concurrency

There are 9 combinations of concurrency and instancing as shown in the below table. In the sections below, we will discuss this in more detail.
InstanceContext
Mode
ConcurrencyMode
Single (Default) Multiple Reentrant
Single
(Single instance for all clients)
Single thread for all clients. Multiple threads for all clients. Single threads for all clients, locks are released when calls diverted to other WCF services.
PerSession (Default)
(Multiple instance per client)
Single thread for every client. Multiple threads for every request. Single threads for all clients, locks are released when calls diverted to other WCF services.
PerCall (Multiple instances for every method call) Single thread for every client. Single thread for every client Single threads for all clients, locks are released when calls diverted to other WCF services.

Instance mode = Per Call and Concurrency = Single

With Per Call, new WCF instances are created for every method call made to the WCF server service. The default concurrency is Single so only one thread will be used to serve all instances.
Below is a simple pictorial representation of what will happen in Per Call and Single concurrency scenarios:
  • For every client instance, a single thread will be allocated.
  • For every method call, a new service instance will be created.
  • A single thread will be used to serve all WCF instances generated from a single client instance.

If you refer the previous sample, you can see how threads are the same and the halt of 5 seconds on the WCF service.

Instance mode = Per Call and Concurrency = Multiple 

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall, 
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloWorldService : IHelloWorldService
{
}
 
In this combination, multiple instances are created for every call but multiple threads serve every method call to a WCF service instance. You can see in the below figure we have two WCF service instances and every instance has multiple WCF service objects created for every method call. Every method call is handled by multiple threads.

In the above sample, if you remember, we have multiple threads serving every method call and the time difference between every method call is reduced considerably. The method calls are fired approximately at the same time.

Instance mode = Per Session and Concurrency = Single

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, 
                 ConcurrencyMode = ConcurrencyMode.Single)]
public class HelloWorldService : IHelloWorldService
{
} 

In this combination, one WCF service instance is created for every WCF client session because the WCF instance mode is set to per session. All the method calls are executed in a sequential manner one by one. In other words, only one thread is available for all method calls for a particular service instance.
If you run the sample code with Per Session and Single combination mode, you will find the same thread executes all requests with the same WCF instance per session.

Instance mode = Per Session and Concurrency = Multiple

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, 
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloWorldService : IHelloWorldService
{
}
 
Instance mode ‘PerSessionconcurrency is the default setting in WCF
In this combination, one WCF instance is created for every WCF client session and every method call is run over multiple threads. Below is a pictorial representation:

If you run the sample code attached with this article, you will find the same instance with every method call running on different methods.

To get a better idea, you can run different client exe instances with different names as shown below. You will notice how every client gets its own WCF service instance with every method allocated to run on different threads.

Instance mode = Single and Concurrency = Single


[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, 
                 ConcurrencyMode = ConcurrencyMode.Single)]
public class HelloWorldService : IHelloWorldService
{
}
In this combination, only one instance of a WCF service instance is created which serves all requests which are sent from all WCF clients. These requests are served using only one thread.

You can see in the below figure approximately one thread is assigned for every WCF client call and only one instance of the WCF service is created.

Instance mode = Single and Concurrency = Multiple

 [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, 
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloWorldService : IHelloWorldService
{}
In this combination, one WCF service instance is created for serving all WCF clients. All requests are served using multiple / different threads.

You can see from the output that we have 6 threads serving 10 requests, as compared to previously we had approximately only two threads.

Reentrant

In this mode, only one thread runs to serve all requests. If your WCF service makes an outbound call to some other WCF service, or makes a client call, it releases the thread lock. In other words, until the outbound call is completed, other WCF clients can not make calls.

Throttling behavior

WCF throttling helps you to put an upper limit on the number of concurrent calls, WCF instances, and concurrent sessions. WCF provides three ways by which you can define upper limits: MaxConcurrentCalls, MaxConcurrentInstances, and MaxConcurrentSessions.
  • MaxConcurrentCalls: Limits the number of concurrent requests that can be processed by WCF service instances.
  • MaxConcurrentInstances: Limits the number of service instances that can be allocated at a given time. When it’s PerCall services, this value matches the number of concurrent calls. For PerSession services, this value equals the number of active session instances. This setting doesn’t matter for Single instancing mode, because only one instance is ever created.
  • MaxConcurrentSessions: Limits the number of active sessions allowed for the service.
All the above three settings can be defined in the servicebehaviors tag as shown in the below XML snippet:
<serviceBehaviors> 




<behavior name="serviceBehavior"> 




<serviceThrottling maxConcurrentCalls="16"
   maxConcurrentInstances="2147483647" maxConcurrentSessions="10" /> 




</behavior> 




</serviceBehaviors>

Default values for WCF throttling

Below is a simple table which shows the default settings for throttling for different WCF versions:
MaxConcurrentSessions MaxConcurrentSessions MaxConcurrentSessions
WCF 3.0 / 3.5 6 26 10
WCF 4.0 16 * processorcount MaxConcurrentCalls MaxConcurrentCalls
+
MaxConcurrentSessions 100 * processorcount
100 * processorcount

Saturday, December 22, 2012

WCF Service in an ASP.Net MVC Application

Introduction

In this article we will see how to access a WCF service and use it in our ASP.Net MVC application. In my previous articles we have seen the creation and consumtion of WCF services by a console client and a WPF client. In this article we will create the client as a MVC application.

For creating a WCF service you can read more over here. For this article we will create one simple WCF service which will return the dataset and in the MVC application we will simply access this WCF service and display the list of authors on the View. So let's start by creating the WCF service.

Creating WCF Author Service

Create a new WCF project in Visual Studio and name it AuthorService. When the service is created a default service will be created; delete it and add a new service to the project and name it ServiceAuthor which will create an 
IServiceAuthor Interface and a ServiceAuthor.cs class. Define one method in IServiceAuthor which returns a Dataset and in ServiceAuthor.cs implement the method which returns the dataset like below. Here I'm creating it on the fly but you can populate it from a database.

IServiceAuthor Code
public interface IServiceAuthor{
     [OperationContract]
     void DoWork();
     [OperationContract]
     DataSet ReturnAuthor();
}


ServiceAuthor.cs

   
public class ServiceAuthor : IServiceAuthor    {
        public void DoWork()
        {

        }
        public System.Data.DataSet ReturnAuthor()
        {
            DataSet ds = new DataSet();            DataTable dt = new DataTable("Author");
            DataColumn dc1 = new DataColumn("AuthorId"typeof(Int32));
            DataColumn dc2 = new DataColumn("Name"typeof(string));
            DataColumn dc3 = new DataColumn("Location"typeof(string));

            dt.Columns.Add(dc1);
            dt.Columns.Add(dc2);
            dt.Columns.Add(dc3);
            DataRow dr1 = dt.NewRow();
            dr1[0] = 10;
            dr1[1] = "Krishna Garad";
            dr1[2] = "India";
            dt.Rows.Add(dr1);
            DataRow dr2 = dt.NewRow();
            dr2[0] = 20;
            dr2[1] = "Mahesh Chand";
            dr2[2] = "USA";
            dt.Rows.Add(dr2);
            ds.Tables.Add(dt);
            return ds;
        }
    }

Now run the service application and copy the address.

Creating MVC client Application

Start a new MVC web application; add the controller in the controller folder with the name Home. Now add the service reference by right-clicking on the solution and selecting Service Reference and paste the copied address in the address box in the opened dialog like below.

wcfwithmvc.gif

Now we also have a service reference, so create the proxy for our WCF service like below in the Home controller.
ClientAuthorReference.ServiceAuthorClient obj = new ClientAuthorReference.ServiceAuthorClient();

Still now we have a proxy for our WCF service; now we can call the methods of our WCF service. On start up only we will show the AuthorList return from WCF service so in the Index Action write the following code and add the view to display the List of Authors.
public ActionResult Index()
{
     DataSet ds = obj.ReturnAuthor();
     ViewBag.AuthorList = ds.Tables[0];
     return View();
}
Add a view to display the list of Authors by looping over the DataTables which we supplied to ViewBag. Write the following code in your aspx page.
<table>        <tr><td>AuthorId</td><td>Name</td><td>Location</td></tr><%foreach (System.Data.DataRow dr in ViewBag.AuthorList.Rows)
  {%>    <tr> <td><%=dr["AuthorId"].ToString()%></td>        
         <td><%=dr["Name"].ToString() %></td>
<td><%=dr["Location"].ToString() %></td>    </tr>        
 <% } %> </table>

In the above markup we are simply reading each row and displaying on the page. Now run the application and view the Author List returned from WCF service.

Sunday, December 16, 2012

CRUD Operations With WCF Odata Service


In this article, I want go into the depth of Odata regarding CRUD operation, Custom entity etc. Before going into depth, it would be better to explain about REST services.

Representational state transfer (REST) is a style of software architecture for World Wide Web. The cool thing about REST is that it is not tied to any particular technology or platform. The term is often used in a looser sense to describe any simple interface which transmits domain-specific data over HTTP without an additional messaging layer such as SOAP or session tracking via HTTP cookies. A RESTFUl web service is a simple web service implemented using HTTP and the principles of REST. Such a web service can be thought of as a collection of resources. The MIME type of the data is supported by the web service. This is often JSON, XML but can be anything. The set of operations are supported by the web service using HTTP methods (e.g.
POST, GET, PUT or DELETE).

WCF Rest Services
WCF Rest Services are normal WCF Services that have added functionality so that they can be consumed in a RESTful manner.
HTTP Verbs supported by WCF Data services are:
  1. GET-To request a specific representation of a resource.
  2. PUT-To create/ update a resource.
  3. Delete-To delete a resource.
  4. POST-Submits data to be processed by the identified resource.
  5. HEAD- Similar to GET, but retrieves only header part and not the body.
Let me to start with OData crud operation.

I have created one OdataDemo Silverlight application. So, I am going to start with Create/Add new resource to the entity and DB. There are two ways to do a CRUD operation:

  1. Using entity object.
  2. DataServiceContext object.
Just like given below:
DataServiceContext
context = new DataServiceContext(new Uri("http://localhost:60259/ODataDemoService.svc/"));
        ODataDemoEntities ObjEntity = new ODataDemoEntities(new Uri("http://localhost:60259/ODataDemoService.svc/"));

I have written code for both using an entity as well as a datacontext object.
  1. Create/Add operation
    Clipboard01.jpg
     
  2. Retrieve resource/resources from DB
    Clipboard02.jpg
     
  3. Update operation

    Clipboard03.jpg
     
  4. Delete operation

    Clipboard04.jpg
     
In this way we can do CRUD operations in a WCF Data Service and a Silverlight Client.

Easiest and Best Way to Use WCF OData Services and Silverlight Client

When I first saw the WCF OData Service template in Visual Studio 2010, really I thought, what is the need for OData Services. Because we already have Web Services, WCF Servicea and REST Services.
But then I was able to understand why when I went through the OData concept.
In this article, I would like to explain the concept of OData. Before starting coding, first I will hook into the basics of OData.

What is OData?
OData is the Open Data Protocol. It is an open web protocol started by Microsoft to expose data using existing web technologies. This is based on Representational State Transfer (REST) full architecture. HTTP, AtomPub (similar to RSS, but specifically introduced special XML format for OData), JSON are all supported.
Here, the URL is the primary operator on the data query.

WCF OData Service

In Visual Studio 2010, there is a template to create a WCF OData service. So, we can easily create an OData Service using Visual Studio 2010.

Example of OData Service has been used


  1. Last (2010) football world cup (S.A), the scoring website was done using an OData Service.
Why should we use an OData Service? 
  1. OData is based on the REST architecture, so we can retrieve data based on an URL.
  2. It also supports HTTP, Atom Pub as well as JSON format.
  3. It has support for any type of data source. Even you can use a custom class as a data source.
  4. No need to create a proxy service object. So, it is lightweight to use.
  5. You can create your own custom methods and expose it.
  6. Since it is lightweight, the interaction between server and client is fast. Thus, performance is good.
  7. It offers full CRUD support by using the different HTTP methods:

    • GET: Gets one or many entries. 
    • POST: Create a new entry. 
    • PUT: Update an existing entry.
    • DELETE: Remove an entry. 
  8. A WCF Data service can expose an entity model via an URI.
  9. A WCF Data service could be consumed by any type of client like Windows, SilverLight, Web, AJAX and console.
Limitations

  1. Since it is purely URL based, it is less secure.
  2. As per my observation, not every query operator in LINQ is available in OData like Filter, Skip, Take etc.
Where is it suitable to use it?

  1. The case in which performance is more important than security. For example, as I said before it was used in the 2010 Football World Cup scoreboard.
Working of a WCF Data Service
There are five components.

  1. DataBase.
  2. Data Access layer using ADO.Net Entity model or LINQ.
  3. Entity Model Implementing Iqueryable and Iupdatable Interface.
  4. WCF Data Service exposing CRUD Operations on entity model as REST Service.
  5. Consuming it on various types of clients.
Supported Message Format
  1. JSON
  2. XML (ATOM)
How do I create and implement an OData Service?
Step 1 : Now let us create one Silverlight application with the name OdataDemo.



Step 2 :
Add one local db to the OdataDemo.Web application. I have created an OdataDemo database with a table called MyTeam as shown in the following screen.



Step 3 : Add an ADO.net Entity model to a web application so that we can expose MyTable using the Entity Framework.



When you click Add, You will get a screen as shown below. Select Generate from the Database template.



It will ask for a database connection as given below.



So, here the entity name is OdataDemoEntities. After clicking next,



You should select a table; you also can select views if are required. After click finish it will expose the table/database.

Step 4 : Add a WCF Data service to the web application. Here, I have named it "OdataDemoService".



When you add the service, it will create a .SVC and .SVC.cs file. The .cs file will be as shown below.



Here we need to make three main changes to access the service.

1. Enter the DataContext name from the Entity model at the top.
2. Here you can give permission for accessing either read/write/both as shown below.
3. Set the operation rule to all.



That's all! It's done now. Build and browse the service; then you can see the result in the form of ATOM.



You can see metadata using http://localhost:60259/ODataDemoService.svc/$metadata

Now, the service is ready to use. Next we will see how to consume it on the client side.


Step 1 : First of all we need to add a service reference to the Silverlight application as given below.



Once you add the service reference, you can access the data context object.



Here, I have taken the service Url and Context object as " ODataDemoEntities ".
Since, Silverlight 4 supports an Asynchronous operation, we should use data service collection or web client. It would be better to use a data service collection, because there is no need to convert it to a list again.

And finally when you run the application, you can see the result as given below.

Insert, Update and Delete Data in GridView Using WCF Service


Introduction
Today, I have provided an article showing you how to insert, delete and update data in a GridView using a WCF service from C# code. To insert, delete and update data in a GridView using a WCF service, we must do the following 3 things:

  1. Create Database Table
  2. Create WCF Service
  3. Create web Application

In the first step we will create a table in SQL Server; after that we create a simple function to insert, delete and update data in a GridView control using a WCF service. In a web application, add a reference of the service to insert, update and delete data in the GridView control. Let's take a look at a practical example. The example application is developed in Visual Studio 2010 and SQL Server 2008.
Step 1: Creating Database Table

  1. Database name:  Registration
  2. Database table name: RegistrationTable
RegistrationTable Table
img1.jpg


Step 2: Creating WCF Service
Now you have to create a WCF Service:

  • Go to Visual Studio 2010
  • New-> Select a project
img2.jpg
Now click on the project and select WCF Service Application and provide a name for the service:

     img3.jpg
    Now click on the Ok Button. Then you will get 3 files in Solution Explorer.
    1. IService.cs
    2. Service.svc
    3. Service.svc.cs
    The following image shows the following files:
    img4.jpg
    For inserting data into the database you need to write the following code in the IService1.cs file which contains the two sections:
    1. OperationContract
    2. DataContract
    The OperationContract section is used to add service operations and a DataContract is used to add types to the service operations.
    Iservice1.cs File
    Now we create a function in the OperationContract section of the Iservice1.cs file:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.Text;
    using System.Data.SqlClient;
    using System.Data;

    namespace WCFServiceForInsert
    {
        // 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 InsertUserDetails(UserDetails userInfo);

            [OperationContract]
            DataSet  SelectUserDetails();

            [OperationContract]
            bool DeleteUserDetails(UserDetails userInfo);

            [OperationContract]
            DataSet UpdateUserDetails(UserDetails userInfo);

            [OperationContract]
            void UpdateRegistrationTable(UserDetails userInfo);
        }

        // Use a data contract as illustrated in the sample below to add composite types to service operations.
        [DataContract]
        public class UserDetails
        {
            int userid;
            string username;
            string password;
            string country;
            string email;



            [DataMember]
            public int UserID
            {
                get { return userid; }
                set { userid = value; }
            }

            [DataMember]
            public string UserName
            {
                get { return username; }
                set { username = value; }
            }
            [DataMember]
            public string Password
            {
                get { return password; }
                set { password = value; }
            }
            [DataMember]
            public string Country
            {
                get { return country; }
                set { country = value; }
            }
            [DataMember]
            public string Email
            {
                get { return email; }
                set { email = value; }
            }
        }
    }
    Service.svc.cs File
    In this file we define the definition of the function InsertUserDetails(UserDetails userInfo).
    And replace the code with the following:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.Text;
    using System.Data.SqlClient;
    using System.Data;

    namespace WCFServiceForInsert
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
        public class Service1 : IService1
        {

            public DataSet SelectUserDetails()
            {
                SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=registration;User ID=sa;Password=wintellect");
                con.Open();
                SqlCommand cmd = new SqlCommand("Select * from RegistrationTable", con);
                SqlDataAdapter sda = new SqlDataAdapter(cmd);
                DataSet ds = new DataSet();
                sda.Fill(ds);
                cmd.ExecuteNonQuery();
                con.Close();
                return ds;
            }

            public bool DeleteUserDetails(UserDetails userInfo)
            {
                SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=registration;User ID=sa;Password=wintellect");
                con.Open();
                SqlCommand cmd = new SqlCommand("delete from RegistrationTable where UserID=@UserID", con);
                cmd.Parameters.AddWithValue("@UserID", userInfo.UserID);
                cmd.ExecuteNonQuery();
                con.Close();
                return true;
            }

            public DataSet UpdateUserDetails(UserDetails userInfo)
            {
                SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=registration;User ID=sa;Password=wintellect");
                con.Open();
                SqlCommand cmd = new SqlCommand("select * from RegistrationTable where UserID=@UserID", con);
                cmd.Parameters.AddWithValue("@UserID", userInfo.UserID);
                SqlDataAdapter sda = new SqlDataAdapter(cmd);
                DataSet ds = new DataSet();
                sda.Fill(ds);
                cmd.ExecuteNonQuery();
                con.Close();
                return ds;
            }

            public void UpdateRegistrationTable(UserDetails userInfo)
            {

                SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=registration;User ID=sa;Password=wintellect");
                con.Open();
                SqlCommand cmd = new SqlCommand("update RegistrationTable set UserName=@UserName,Password=@Password,Country=@Country, Email=@Email where UserID=@UserID", con);
                cmd.Parameters.AddWithValue("@UserID", userInfo.UserID);
                cmd.Parameters.AddWithValue("@UserName", userInfo.UserName);
                cmd.Parameters.AddWithValue("@Password", userInfo.Password);
                cmd.Parameters.AddWithValue("@Country", userInfo.Country);
                cmd.Parameters.AddWithValue("@Email", userInfo.Email);
                cmd.ExecuteNonQuery();
                con.Close();
            }

            public string InsertUserDetails(UserDetails userInfo)
            {
                string Message;
                SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=registration;User ID=sa;Password=wintellect");
                con.Open();
                SqlCommand cmd = new SqlCommand("insert into RegistrationTable(UserName,Password,Country,Email) values(@UserName,@Password,@Country,@Email)", con);
                cmd.Parameters.AddWithValue("@UserName", userInfo.UserName);
                cmd.Parameters.AddWithValue("@Password", userInfo.Password);
                cmd.Parameters.AddWithValue("@Country", userInfo.Country);
                cmd.Parameters.AddWithValue("@Email", userInfo.Email);
                int result = cmd.ExecuteNonQuery();
                if (result == 1)
                {
                    Message = userInfo.UserName + " Details inserted successfully";
                }
                else
                {
                    Message = userInfo.UserName + " Details not inserted successfully";
                }
                con.Close();
                return Message;
            }
        }
    }

    Testing the Service
    Press F5 to run the service. A WCF Test Client form will be displayed and it will load the service.
    img5.jpg
    Now double-click the InserUserDetails() method under IService1. The InserUserDetails tab will be displayed.
    img7.jpg
    The service was added successfully.
    Now open the service in the browser.
    Now right-click on the service1.vcs -> open in browser:
    img6.jpg
    Now copy the URL.
    img8.jpg
    URL
    http://localhost:2268/Service1.svc
    Step 3: Create web Application (Accessing the Service)
    Now, you have to create a web site.
    • Go to Visual Studio 2010
    • New-> Select a website application
    • Click OK
    img9.gif
    Now add a new page to the website:
    • Go to the Solution Explorer
    • Right-click on the Project name
    • Select add new item
    • Add new web page and give it a name
    • Click OK
    img10.gif
    When we click on the add the service reference the following window will be opened:
    img11.jpg
    Now paste the above URL in the address and click on the go button.
    img12.jpg
    Click on the Ok Button. Now the reference has been added in the Solution Explorer.
    img13.jpg
    Now create a new website and drag and drop controls onto the aspx page. The aspx code is the following:
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="WcfServiceselectInsert.aspx.cs"
        Inherits="WcfServiceselectInsert" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <div>
                <table width="84%" cellpadding="0" cellspacing="0" style="border: solid 1px #3366CC;">
                    <tr>
                        <td colspan="4" style="height: 30px; background-color: #f5712b;">
                            <span class="TextTitle" style="color: #FFFFFF;">Registration Form</span>
                        </td>
                    </tr>
                    <tr>
                        <td height="20px" colspan="0">
                        </td>
                    </tr>
                    <tr>
                        <td width="50%" valign="top">
                            <table id="TableLogin" class="HomePageControlBGLightGray" cellpadding="4" cellspacing="4"
                                runat="server" width="100%">
                                <tr>
                                    <td colspan="3" align="center">
                                        <asp:Label ID="LabelMessage" ForeColor="Red" runat="server" EnableViewState="False"
                                            Visible="False"></asp:Label><br>
                                    </td>
                                </tr>
                                <tr style="font-weight: normal; color: #000000">
                                    <td align="right">
                                        <span>UserName:</span>;
                                    </td>
                                    <td align="left" style="padding-left: 10px;">
                                        <asp:TextBox ID="TextBoxUserName" runat="server" CssClass="textbox" Width="262px"
                                            MaxLength="50" Height="34px"></asp:TextBox>
                                    </td>
                                </tr>
                                <tr>
                                    <td align="right">
                                        <span class="TextTitle">Password:</span>
                                    </td>
                                    <td align="left" style="padding-left: 10px;">
                                        <asp:TextBox ID="TextBoxPassword" runat="server" CssClass="textbox" Width="261px"
                                            MaxLength="50" Height="34px"></asp:TextBox>
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td align="right">
                                        <span class="TextTitle">Country:</span>
                                    </td>
                                    <td align="left" style="padding-left: 10px;">
                                        <asp:TextBox ID="TextBoxCountry" runat="server" CssClass="textbox" Width="258px"
                                            MaxLength="50" Height="34px"></asp:TextBox>
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td align="right">
                                        <span class="TextTitle">Email:</span>
                                    </td>
                                    <td align="left" style="padding-left: 10px;">
                                        <asp:TextBox ID="TextBoxEmail" runat="server" CssClass="textbox" Width="258px" MaxLength="50"
                                            Height="34px"></asp:TextBox>
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td align="right">
                                    </td>
                                    <td align="left" style="padding-left: 10px;">
                                        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" Width="87px" />
                                        <br />
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                    </td>
                                    <td>
                                        <asp:GridView ID="CategoriesGridView" runat="server" AutoGenerateColumns="False"
                                            CellPadding="4" DataKeyNames="UserID" AllowSorting="True" PagerStyle-HorizontalAlign="left"
                                            Width="100%" BackColor="#FFFFCC">
                                            <HeaderStyle HorizontalAlign="Left" />
                                            <Columns>
                                                <asp:TemplateField HeaderText="UserName ">
                                                    <ItemTemplate>
                                                        <asp:Label ID="LabelUserName" runat="server" Text='<%#Eval("UserName") %>'></asp:Label>
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField HeaderText="Password">
                                                    <ItemTemplate>
                                                        <asp:Label ID="LabelLPassword" runat="server" Text='<%#Eval("Password") %>'></asp:Label>
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField HeaderText="Country ">
                                                    <ItemTemplate>
                                                        <asp:Label ID="LabelCountry" runat="server" Text='<%#Eval("Country") %>'></asp:Label>
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField HeaderText="Email">
                                                    <ItemTemplate>
                                                        <asp:Label ID="LabelEmail" runat="server" Text='<%#Eval("Email") %>'></asp:Label>
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField HeaderText="Edit">
                                                    <ItemTemplate>
                                                        <asp:ImageButton ID="ImageButtonEdit" runat="server" CausesValidation="false" CommandArgument='<%#Eval("UserId") %>'
                                                            OnCommand="CategoryImageButtonEdit_Command" ImageUrl="~/Images/Edit.png"
                                                            ToolTip="Edit" />
                                                    </ItemTemplate>
                                                    <ItemStyle Width="100px" />
                                                </asp:TemplateField>
                                                <asp:TemplateField HeaderText="Delete">
                                                    <ItemStyle Width="100px" HorizontalAlign="Left" />
                                                    <ItemTemplate>
                                                        <asp:ImageButton ID="ImageButtonDelete" runat="server" CausesValidation="false" CommandArgument='<%#Eval("UserId") %>'
                                                            CommandName="Delete" OnCommand="CategoryButtonDelete_Command" ImageUrl="~/Images/cross.gif"
                                                            ToolTip="Delete" />
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                            </Columns>
                                            <FooterStyle BackColor="#FFFFCC" ForeColor="#330099" />
                                            <PagerStyle HorizontalAlign="Left"></PagerStyle>
                                            <RowStyle CssClass="GridItems" />
                                            <HeaderStyle CssClass="GridHeader" />
                                        </asp:GridView>
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
        </form>
    </body>
    </html>

    The designing form looks like below:

    img14.jpg

    Double-click the button, and add the following code in the click event handler:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    using ServiceReference1;
    using System.IO;

    public partial class WcfServiceselectInsert : System.Web.UI.Page
    {
        ServiceReference1.Service1Client objServiceClientobjService = new ServiceReference1.Service1Client();
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                showdata();
            }
        }

        private void showdata()
        {
            DataSet ds = new DataSet();
            ds = objServiceClientobjService.SelectUserDetails();
            CategoriesGridView.DataSource = ds;
            CategoriesGridView.DataBind();

        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (Button1.Text == "Update")
            {
                updateuserdetail();
                TextBoxUserName.Text = string.Empty;
                TextBoxPassword.Text = string.Empty;
                TextBoxCountry.Text = string.Empty;
                TextBoxEmail.Text = string.Empty;
                Button1.Text = "Submit";
            }
            else
            {
                insertuserdetail();
                showdata();
            }
        }

        private void insertuserdetail()
        {
            UserDetails userInfo = new UserDetails();
            userInfo.UserName = TextBoxUserName.Text;
            userInfo.Password = TextBoxPassword.Text;
            userInfo.Country = TextBoxCountry.Text;
            userInfo.Email = TextBoxEmail.Text;
            string result = objServiceClientobjService.InsertUserDetails(userInfo);
            LabelMessage.Text = result;
            showdata();
        }

        protected void CategoryButtonDelete_Command(object sender, System.Web.UI.WebControls.CommandEventArgs e)
        {
            UserDetails userInfo = new UserDetails();
            userInfo.UserID = int.Parse(e.CommandArgument.ToString());
            objServiceClientobjService.DeleteUserDetails(userInfo);
            showdata();
        }

        protected void CategoryImageButtonEdit_Command(object sender, System.Web.UI.WebControls.CommandEventArgs e)
        {

            UserDetails userInfo = new UserDetails();
            userInfo.UserID = int.Parse(e.CommandArgument.ToString());
            ViewState["UserId"] = userInfo.UserID;
            DataSet ds = new DataSet();
            ds = objServiceClientobjService.UpdateUserDetails(userInfo);

            if (ds.Tables[0].Rows.Count > 0)
            {
                TextBoxUserName.Text = ds.Tables[0].Rows[0]["UserName"].ToString();
                TextBoxPassword.Text = ds.Tables[0].Rows[0]["Password"].ToString();
                TextBoxCountry.Text = ds.Tables[0].Rows[0]["Country"].ToString();
                TextBoxEmail.Text = ds.Tables[0].Rows[0]["Email"].ToString();
                Button1.Text = "Update";
            }
        }

        private void updateuserdetail()
        {
            UserDetails userInfo = new UserDetails();

            userInfo.UserID = int.Parse(ViewState["UserId"].ToString());
            userInfo.UserName = TextBoxUserName.Text;
            userInfo.Password = TextBoxPassword.Text;
            userInfo.Country = TextBoxCountry.Text;
            userInfo.Email = TextBoxEmail.Text;
            objServiceClientobjService.UpdateRegistrationTable(userInfo);
            showdata();
        }
    }

    Now run the application.

    Press CTRL+F5 to run the project:

    img15.jpg

    Now enter the UserName, Password, country and Email and click on the button.

    img16.jpg
    Now click on the button. Data will be saved in the database table and also displayed in the GridView on the form.

    img17.jpg

    We can also insert more data.

    img18.jpg

    Now click on Delete Image to delete the record where the username is manish in the GridView.

    img19.jpg

    Now click on the edit Image to update the record where the username is Rohatash Kumar in the GridView. The data will be displayed in the TextBoxes.

    img20.jpg

    Now replace username with Name Sanjay and  email id with  sanjay@gmail.com and click on the update Button. The updated data will be displayed in the GridView and also will be updated in the database table.

    img21.jpg