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 are “guidelines”.
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)
{
}
- 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
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.
[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);
}
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