Introduction
Following article will cover, how to build a RESTful service using the WCF framework. What I also want to achieve is to have multiple end points.
1. RESTful end point
2. TCP IP end point.
By doing this, we can try to cater to different set of clients. RESTful services can be accessed by all kind of clients and TCP IP can be access by .Net clients. As many of you would already aware that the TCP/IP is the best suited for better performance. At the end of article, I will also cover how you can test your REST based service using a fiddler tool.
What is REST
• REST stands for Representational State Transfer
• REST is about accessing resources through a universal interface.
• REST URI: Uniform Resource Identifier - This is a unique way of identifying resources on the network.
• You can also refer following link to get to know all REST terminologies.
http://msdn.microsoft.com/en-us/library/dd203052.aspx
Steps used to Achieve the above stated Objective
Add Services
• Add a library project to a solution
• Implement services using IService interface and Service Contract.
• Service will in turn interact with Northwind database.
Host Services
• Add a console application and
• Configure the app.config with TCP/IP and RESFful service.
• Host services in the console application.
Test Services
• Create a windows application to consume services.
1. RESTful endpoint
2. TCP/IP endpoint
• Test Restful Services using Browser and Fiddler tool
Add Services
• Create a .Net solution
• Add a library project with name SampleServices.
• Add “LINQ to SQL” class, Northwind.dbml.
I want to communicate to category table of Northwind database. Once you have Added Northwind.dbml file, connect to a local server using server explorer in the LINQ designer. Then drag and drop category table on to the LINQ designer.
• You will have to change the SQL connection string to point to your local server, which has northwind database.
• Add c# classes IService and Service
• Make sure you add following reference System.ServiceModel & System.ServiceModel.Web
• IService Interface Code
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(UriTemplate = "/Category/{categoryID}", Method = "GET")]
Category GetCategory(string CategoryID);
[OperationContract]
[WebInvoke(UriTemplate = "/Category", Method = "GET")]
List
<category /> GetCategories();
[OperationContract]
[WebInvoke(UriTemplate = "/Category/Add", Method = "POST")]
bool AddCategory(Category category);
}
• Service Code
public class Service : IService
{
public Category GetCategory(string categoryID)
{
NorthwindDataContext context = new NorthwindDataContext();
var category = context.Categories.SingleOrDefault(e => e.CategoryID == Convert.ToInt32(categoryID));
context.Dispose();
return category;
}
public List
<category /> GetCategories()
{
NorthwindDataContext context = new NorthwindDataContext();
var categories = context.Categories.ToList();
context.Dispose();
return categories;
}
public bool AddCategory(Category category)
{
NorthwindDataContext context = new NorthwindDataContext();
context.Categories.InsertOnSubmit(category);
context.SubmitChanges();
context.Dispose();
return true;
}
}
Host Services
• Add a console application “ServiceHost”
• Make sure you add reference to System.ServiceModel assembly.
• Add Reference to SampleService.dll
• Configure the app.config to support REST and TCP/IP endpoints
<system.serviceModel>
<services>
<service name="SampleServices.Service" behaviorConfiguration="MYServiceBehavior">
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="net.tcp://localhost:12000/SampleServices/Service" binding="netTcpBinding" bindingConfiguration="TCPBindingDetails" contract="SampleServices.IService" behaviorConfiguration="TCPBehavior">
</endpoint>
<endpoint name="webHttpBinding" address="REST" binding="webHttpBinding" behaviorConfiguration="RESTBehavior" contract="SampleServices.IService" />
<host>
<baseAddresses>
<add baseAddress="<a href="http:
</baseAddresses>
<timeouts closeTimeout="01:20:10" openTimeout="01:20:00" />
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="TCPBindingDetails" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="5000000" maxBufferSize="5000000" maxConnections="10" maxReceivedMessageSize="5000000">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:30:00" enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<clear />
<behavior name="TCPBehavior">
<dataContractSerializer maxItemsInObjectGraph="6553600" />
</behavior>
<behavior name="RESTBehavior">
<dataContractSerializer maxItemsInObjectGraph="6553600" />
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MYServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Note: helpEnabled="true"<webhttp helpenabled="true">, is used to enable Automatic help pages for the RESTful service
• Hosting code in program.cs
static void Main(string[] args)
{
System.ServiceModel.ServiceHost serviceHost = new
System.ServiceModel.ServiceHost(typeof(SampleServices.Service));
serviceHost.Open();
Console.WriteLine("Services are ready & running.");
Console.WriteLine();
Console.ReadLine();
}
Test Services
• Create a windows application, “Client”
• Add references to System.ServiceModel & System.Runtime.Serialization
• Generate proxy using svcutil.exe
• Add proxy class to the client application.
• Sample code to access TCP IP end point.
ServiceClient client = new ServiceClient();
var allCategories = client.GetCategories();
MessageBox.Show(allCategories.Count().ToString());
• Sample Code to access REST service.
WebRequest request = WebRequest.Create("http://localhost:9002/SampleServices/Service/REST/Category/1");
WebResponse ws = request.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding(1252);
StreamReader responseStream = new StreamReader(ws.GetResponseStream());
string response = responseStream.ReadToEnd();
responseStream.Close();
MessageBox.Show(response);
• You can also test the REST based services through Browser and Fiddler tool.
• Important TIP: You can get to know following items by enabling help on the service
o URI
o Method type
o Description
o Data format expected for GET method
o Data format or Request Body for POST method.
You can get all these information by browsing to http://localhost:9002/SampleServices/Service/REST/help
Clicking on the method will provide the sample response XML
Clicking on the POST method will provide the Request xml to be sent.
Get all categories in browser using RESTful service http://localhost:9002/SampleServices/Service/REST/Category
• Get the details of the category whose ID = 1, http://localhost:9002/SampleServices/Service/REST/Category/1
• Using Fiddler: Go to request builder in the fiddler tool and type in the url, select GET method. Then click execute button. url: http://localhost:9002/SampleServices/Service/REST/Category/
Note: Make sure that you are running the WCF host
• You can see the response by double clicking on the request in web session panel.
• You can see the use the fiddler for POST method also. In order add a category, we need to use URI http://localhost:9002/SampleServices/Service/REST/Category/Add , which is a POST method. We can get the request xml by using the help url.
2147483647 String content String content 1999-05-31T11:20:00 QmFzZSA2NCBTdHJlYW0=
Let us use the above format in the Fiddler tool add a new category. Remove CategoryID, as this is auto generated column in the database. Use the below format in the Fiddler tool
New Category New Category 2012-05-31T11:20:00
• Select “POST” method in the method. Provide url
http://localhost:9002/SampleServices/Service/REST/Category/Add
Add content-type: application/xml in the request header.
Add the above XML in the request body.
• Click Execute and check in DB, if the category is inserted. You can also check it by using RESTfule service in browser. http://localhost:9002/SampleServices/Service/REST/Category
Resources
http://benjii.me/2010/03/5-lifesaving-tips-for-creating-a-wcf-restful-api-in-net-4/
Conclusion
Article covers having multiple endpoints for the WCF service. Service was configured with TCP/IP and RESTful endpoint. This might be useful in those projects, where you would want your services to be consumed by both .Net and other varied clients. .Net application can still communicate with TCP/IP endpoint, which provides the optimal performance; where as other clients can communicate with RESTful end point. I have also tried to cover different ways to test the services. We can also use WCF REST started kit to create service. I am yet to use it, and will elaborate it once I start using it.