Tuesday, May 21, 2013

WCF- REST



REST (Representational State Transfer)

·    REST is an architectural style for building services.Services that follow this style are known as RESTful service.

·     REST services are built to follow the specific constraints of the REST architectural style. Architectural constraints areguidelines”. Some services will use all of these constraints, and some will use only some of the constraints.

·     A RESTful client-server system is stateless, meaning each request against the server contains all the information the server needs to process it; and cacheable, in that the server can specify whether and for how long resource representations can be cached either locally on the client or on intermediate servers between the client and the server.

Basic elements required to build WEB HTTP services with WCF

Resources : The first thing to do when designing a RESTful service is to determine which resources
you are going to expose. Resource is any information that we want to make available to others.
URIs and URI Processing : (A resources are uniquely identified by a URI) .  URIs play a central role in the design of WEB HTTP services. The WCF WEB HTTP programming model uses the Uri Template and UriTemplateTable classes to provide URI processing capabilities.
UriTemplate : URI template allows you to define a set of structurally similar URIs. Namespace (System.ServiceModel.Web)  
UriTemplate literal and mix literal and variable values
              UriTemplate L1 = new UriTemplate("/weather/");
               UriTemplate L2 = new UriTemplate("/weather/{city}");
 UriTemplate Special Values
UriTemplate root = new UriTemplate("/");
              UriTemplate matchAll = new UriTemplate("*"); 

   UriTemplate will match every URI
  •    Each segment can have a literal value eg : weather/WA/Seattle
  •    variable value within curly braces { }
  •   * the rest of the path
  •   Query Expression can be passed

UriTemplateMatch :
    
// Setup a template.
UriTemplate template1 = new UriTemplate("user/blog/{year}/{month}/{day}/*");

// Setup the base address for my blog.
Uri baseAddress = new Uri("http://abc.com");

// Create a user uri and match against it using the template.
Uri UserUri = new Uri("http://abc.com/user/blog/2012/03/17/topic.aspx");
UriTemplateMatch match = template1.Match(baseAddress, UserUri);

// Check if  match is successful.
if (match != null)
{
}

     UriTemplateTable :
  • UriTemplates are stored as an ILIst of KeyValuePairs. 
  •  UriTemplateTable provides support for storing a set of related UriTemplates. 

     
// Setup a template table for the base address.
UriTemplateTable table = new UriTemplateTable(new Uri("http://www.Blogs.com/User"));

// Add the templates to the table.
table.KeyValuePairs.Add(
    new KeyValuePair<UriTemplate, object>(
    new UriTemplate("Posted/{year}/"),
    "Yearly Info"));

table.KeyValuePairs.Add(
    new KeyValuePair<UriTemplate, object>(
    new UriTemplate("Posted/{year}/{month}/"),
    "Yearly monthly Info"));

table.KeyValuePairs.Add(
    new KeyValuePair<UriTemplate, object>(
    new UriTemplate("Posted/{year}/{month}/{day}/"),
    "yearly monthly day info"));


// Create a candidate uri for a match.
Uri candidateUri = new Uri("http://www.Blogs.com/User/Posted/2007/01/");

// Tell the table to match against the uri.
Collection<UriTemplateMatch> matchResults = table.Match(candidateUri);

// Check if a match was found.
if ((matchResults != null) && (matchResults.Count > 0))
{
    // Write out each result.
    foreach (UriTemplateMatch match in matchResults)
    {
        Console.WriteLine();
        Console.WriteLine("Template: " + match.Template.ToString());
        Console.WriteLine("Parameters");

        foreach (string key in match.BoundVariables.Keys)
        {
  Console.WriteLine("   Name: {0} | Value: {1}", key, match.BoundVariables[key]);
        }
    }
}


Resource Representations :

·         XML
·         RSS/Atom
·         XHTML
·         JSON
·         Other media types
      
Hypertext Transfer Protocol

Hypertext Transfer Protocol (HTTP) is a stateless. Client send request goes from the client to the server, and the response goes from the server back to the client.

HTTP request has three parts: HTTP method (or "verb"), URI and the HTTP version. E.g. GET /article/1/ HTTP/1.1
HTTP response has three parts: HTTP status code, indicating the status of the requested, URI, e.g.HTTP/1.1 200 OK

HTTP Methods
HTTP defines several methods, or "verbs", to execute on a resource: HEAD, GET, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, and PATCH

GET Method
·         Retrieves a resource (idempotent)
·         Safe (guaranteed not to cause side-effet)
·         Cacheable
·         GET requests do not include a message body, but GET responses usually do
.
POST Method
·         Creates a new resource
·         Unsafe, effect of this verb isn’t defined by HTTP
·         POST requests require a message body, i.e. the data to be processed.

PUT Method
·         Updates an existing resource
·         Used for resource creation when client knows URI
·         Can call N times, same thing will always happen (idempotent)
·         PUT requests must include a message body (the resource to be placed at the URL).

DELETE Method
·         Removes a resource
·         Can call N times, same thing will always happen (idempotent)
·         DELETE requests do not require a message body.

 
WebGet and WebInvoke Attributes

WebGet

·         The WebGetAttribute attribute is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as the HTTP protocol Get verb.

·         The association with HTTP Get verb means that the operation is used to retrieve information from the service.

·         Applying the WebGetAttribute attribute to a service operation has no effect unless a behavior that is looking for this metadata in the operation description (such as WebHttpBehavior) is added to the service's behavior collection.

[ServiceContract]
public interface ICalculator
{
    [OperationContract]
    [WebGet]
    long Addition(long x, long y);

    [OperationContract]
    [WebGet(UriTemplate = "Sub?x={x}&y={y}", BodyStyle = WebMessageBodyStyle.Bare)]
    long Division(long x, long y);

    [OperationContract]
    [WebGet(UriTemplate = "Div?x={x}&y={y}", RequestFormat = WebMessageFormat.Xml)]
    long GetValue (long x, long y);

    [OperationContract]
    [WebGet(ResponseFormat= WebMessageFormat.Json)]
    long Mod(long x, long y);
}

   [ServiceContract]
    public interface IEmpInfo
    {
        [OperationContract]
        [WebGet(
            BodyStyle = WebMessageBodyStyle.Bare,
            RequestFormat = WebMessageFormat.Xml,
            ResponseFormat = WebMessageFormat.Xml,
            UriTemplate = "/GetEnployee/{EmpID}")]
        string getEmployeeFullName(int EmpID);
    }

Body Style:
·         WebMessageBodyStyle.Bare
·         WebMessageBodyStyle.Wrapped
·         WebMessageBodyStyle.WrappedRequest
·         WebMessageBodyStyle.WrappedResponse
          
RequestFormat and ResponseFormat:

·         WebMessageFormat.Xml
·         WebMessageFormat.Json



WebInvoke

The WebInvokeAttribute attribute is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as an underlying transport verb that represents an invocation (for example, HTTP POST, PUT, or DELETE).

WebInvokeAttribute includes all of the same properties that WebGetAttribute has, but also includes a Method property.

  WebInvokeAttribute defaults to POST but you can use it for other verbs too.


[ServiceContract]
    public interface ICalculator2
    {
        [OperationContract]
        [WebInvoke]
        long Add(long x, long y);

        [OperationContract]
        [WebInvoke(UriTemplate = "Mult?x={x}&y={y}", BodyStyle = WebMessageBodyStyle.Bare)]
        long Multiply(long x, long y);

        [OperationContract]
        [WebInvoke(UriTemplate = "Div?x={x}&y={y}", RequestFormat = WebMessageFormat.Xml, ResponseFormat         = WebMessageFormat.Xml)]
        long Divide(long x, long y);

        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "save?x={x}&y={y}")]
        int Insertrecord(long x, long y);

               [WebInvoke(UriTemplate = "customers/{id}", Method = "PUT")]
                UserDataContract UpdateUSer(string id, UserDataContract newUSer);

                [WebInvoke(UriTemplate = "getcustomersdetails/{id}", Method = "GET")]
                 UserDataContract UpdateUSer(string id);


    }


WebHttpBinding

Like BasicHttpBinding (mainly for interoperability but less security) and wsHttpBinding ( more security features,support session full services, reliable messaging, transactional control ) are two SOAP-based bindings. 



The WebHttpBinding class is a new binding in WCF 3.5, designed to be the binding for RESTful WCF endpoints and response to Http request instead of soap.

WebHttpBinding contains a binding element that creates the HTTP (or HTTPS) WCF transport channel to listen for or send messages over HTTP(S).

WebHttpBehavior

        Gets or sets a value that determines if the WCF Help page is enabled.
         <endpointBehaviors>
              <behavior name="EndpointBehavior">
                <webHttp helpEnabled="true" defaultBodyStyle="Wrapped" />
              </behavior>
            </endpointBehaviors>  



Exmaple 

Interface :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebGet]
    string GetMessage(string inputMessage);
    [OperationContract]
    [WebInvoke]
    string PostMessage(string inputMessage);
}


Service :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

public class Service1 : IService1
{
    public string GetMessage(string inputMessage)
    {
        return "Calling Get for you " + inputMessage;
    }
    public string PostMessage(string inputMessage)
    {
        return "Calling Post for you " + inputMessage;
    }
}


Webconfig :
<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="RESTServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpointBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
   
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>

    <services>
     
      <service name="Service1"   behaviorConfiguration="RESTServiceBehavior ">

<endpoint address="" binding="webHttpBinding" contract="IService1"  behaviorConfiguration="EndpointBehavior"/>
     
      </service>
    </services>  
   
   
  </system.serviceModel> 
 
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
 
</configuration>
 

Right click on service and view in service in browser 

 



Type URL with Method Name
  


 


Note: In url we are passing Service Name with extension as well
To avoid this We use ASP.NET Routing Integration feature
  
To use ASP.NET Routing Integration  we need to do following steps:


Step-1: Turn on ASP.NET compatibility in web config file

  <serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true" />

Step-2 : Add the UrlRoutingModule and UrlRoutingHandler into  web.config file. We can place this under <system.webServer> </system.webServer> element and after closing </system.serviceModel> element.


<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule"
           type="System.Web.Routing.UrlRoutingModule,
          System.Web.Routing, Version=4.0.0.0,
          Culture=neutral,
          PublicKeyToken=31BF3856AD364E35" />

    </modules>
    <handlers>
      <add name="UrlRoutingHandler"
         preCondition="integratedMode"
         verb="*" path="UrlRouting.axd"
         type="System.Web.HttpForbiddenHandler,
         System.Web, Version=4.0.0.0, Culture=neutral,
         PublicKeyToken=b03f5f7f11d50a3a" />
    </handlers>
  </system.webServer>
 
 
Step 3: Add a global.asax file to your project by right clicking on the project in the solution 

explorer, select Add> New Item> Global Application Class. Within the Application_Start

  method  add a Route to the RouteTable.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Syndication;
using System.Web.Routing;

namespace WcfService1
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            // Service1 is service class
            RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(Service1)));
        }
        protected void Session_Start(object sender, EventArgs e)
        {}
        protected void Application_BeginRequest(object sender, EventArgs e)
        {}
        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {}
        protected void Application_Error(object sender, EventArgs e)
        {}
        protected void Session_End(object sender, EventArgs e)
        {}
        protected void Application_End(object sender, EventArgs e)
        {}
    }
}

Step 4: In webconfig we set  aspNetCompatibilityEnabled="true" so we need to defined AspNetCompatibilityRequirements at service level to make sure that Service can run under  ASP.NET compatibility code.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class Service1 : IService1
{
    public string GetMessage(string inputMessage)
    {
        return "Calling Get for you " + inputMessage;
    }
    public string PostMessage(string inputMessage)
    {
        return "Calling Post for you " + inputMessage;
    }
}



Next Again Right click on service and view in browser and change URL to

 

Console Application for Client :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Description;


namespace WCF_REST_1
{
    class Program
    {
        static void Main(string[] args)
        {
            ChannelFactory<IService1> cf = new ChannelFactory<IService1>(new WebHttpBinding(), "http://localhost:64946");
            cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
            IService1 channel = cf.CreateChannel();
            Console.WriteLine(channel.GetMessage("Get message for Client"));
            Console.WriteLine(channel.PostMessage("Message post by client"));
            Console.Read();
           
     
        }
    }
}

OutPut :
 


No comments :

Post a Comment