« Defining solution in ERP: Ten Commandments - Thy shall not falter on them! | Main | MYOC - Make Your Opinion Cloud- Series 2 »

MYOC - Building RESTful services on Azure

In this post on the MYOC series, we will look at how RESTful services can be build on Windows Azure. Building RESTful services may be no different than how you would do it traditionally on-premise. Nonethless this post will detail the steps in building REST services in Azure and additional steps which need to be considered while developing a service for Azure.

Highlighted below are the steps which differ.

REST (Representational State Transfer) is an architecture style that leverages the existing technology and protocols of the Web, like HTTP and XML. REST describes how distributed resources can be defined and addressed for simple communication and high scalability. REST specified how resources can be defined and then addressed  using Universal Resource Identifier(URI) like a web address. REST leverages http programming model and uses the same HTTP web methods for resources too –

a. GET – to get a resource
b. POST – to insert into a resource
c. PUT – to update a resource
d. DELETE – to delete a resource

REST services are easily discoverable through Web URLs and can be consumed by any http client, thus offering a great deal of interoperability between heterogeneous systems. 

WCF (Windows Communication Foundation) is Microsoft’s unified programming model for building service-oriented applications. It enables developers to build secure, reliable, transacted solutions that integrate across platforms and interoperate with existing investments.  A WCF Service uses three types of contracts –

a. Service contract to communicate with its client
b. operation contract for each of the methods in a service
c. Data contract  for request and response data

In WCF Service, the REST based call of the service methods will be allowed by specifying WebGet (for GET method) or WebInvoke(for POST method) attribute in the service interface.

Following are the steps to create REST based WCF service using Visual Studio 2008 –

1. Open the Visual Studio 2008 and create a cloud service project. Right click on the web role project and click on Add -> New Item. All the aspx pages, web services and WCF services are required to add in web role project. [Additional step for Azure Projects]

2. Now select WCF Service from the templates and provide a name of service and click on Add button.

3. This will add 3 files in the project –

a. IMyTestService.cs – the interface file which contains method declarations.
b. MyTestService.svc – the mark up file which contains information about service like code language, mode of application, service namespace, name of code behind file etc.
c. MyTestService.svc.cs – the code behind file which contains actual implementation of the methods declared in the interface definition.

4. The <system.serviceModel> section of the web.config of the project should be as shown below –

<system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="MyCloudApp_WebRole.MyTestServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
            <endpointBehaviors>
              <behavior name="webHttp">
                <webHttp />
              </behavior>
            </endpointBehaviors>
        </behaviors>
        <bindings>
            <webHttpBinding>
                <binding name="webHttp" maxReceivedMessageSize="50000000" maxBufferPoolSize="50000000">
                    <readerQuotas maxArrayLength="50000000" />
                </binding>
            </webHttpBinding>
        </bindings>
          <services>
            <service behaviorConfiguration="MyCloudApp_WebRole.MyTestServiceBehavior" name="MyCloudApp_WebRole.MyTestService">
                <endpoint address="" binding="webHttpBinding" contract="MyCloudApp_WebRole.IMyTestService" bindingConfiguration="webHttp" behaviorConfiguration="webHttp" />                   
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            </service>
        </services>
</system.serviceModel>

5. Create a Data Entity class file with Data Contract attribute as mentioned below –

a. Add reference of ‘System.Runtime.Serialization’ and add below namespace after existing ones

using System.Runtime.Serialization; 

b. Decorate the class with DataContract attribute and class members with DataMember attribute

namespace MyCloudApp_WebRole
{
    [DataContract]
    public class Poll
    {
        [DataMember]
        int pollId;

        [DataMember]
        string pollName;

        [DataMember]
        string pollQuestion;
    }
}

c. DataContract attribute has following input parameters –

i. IsReference – boolean value to indicate if data contract is a reference
ii. Name – name of the data contract for the type
iii. Namespace – namespace of the data contract for the type

d. DataMember attribute has following input parameters –

i. EmitDefaultValue – boolean value to indicate if there is a default value
ii. IsRequired – boolean value to indicate if the data member is mandatory field
iii. Name – name of data member
iv. Order – order of data member to appear in the data contract

6. Now open the IMyTestService.cs file and perform below steps –

a. Add reference of ‘System.ServiceModel.Web’ and add below namespaces after existing ones

using System.ServiceModel.Web; 

b. Add method declaration in the service interface and decorate with WebGet / WebInvoke attribute

namespace MyCloudApp_WebRole
{   
    [ServiceContract]
    public interface IMyTestService
    {
  [WebInvoke(Method = "POST", UriTemplate = "Poll")]
  [OperationContract]       
  void CreatePoll(MyCloudApp_WebRole.Poll poll);
   
        [WebGet(UriTemplate = "Poll/Id/{pollId}",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare)]
        [OperationContract]
        MyCloudApp_WebRole.Poll GetPollbyId(string pollId);
    }
}

c. Follow the guidelines to create a URI template for a service method.
 
d. ServiceContract attribute is used to define a service contract. Service contract is exposed to the service consumer to call the service. Service contract attribute has following properties –

i. CallbackContract – specifies the return contract in a duplex conversation
ii. ConfigurationName – the name of the service element in the configuration file to use
iii. HasProtectionLevel – indicates whether all messages supporting the contract have an explicit ProtectionLevel value
iv. Name – name of the contract in the WSDL <portType> element
v. Namespace – namespace of the contract in the WSDL <portType> element
vi. ProtectionLevel – the level of protection for the messages
vii. SessionMode – specifies whether the contract requires a binding that supports sessions

e. OperationContract attribute marks the methods exposed by the service in the service contract in a WCF service. it has following properties –

i. Action - specifies the action performed by the operation.
ii. AsyncPattern - indicates that the operation is implemented or can be called asynchronously using a Begin/End method pair.
iii. HasProtectionLevel - indicates whether the ProtectionLevel property has been explicitly set.
iv. IsOneWay - indicates that the operation only accepts input message and doesn’t return any output message.
v. IsInitiating - specifies whether this operation can be the initial operation in a session.
vi. IsTerminating - specifies whether WCF attempts to terminate the current session after the operation completes.
vii. ProtectionLevel - specifies the message-level security that an operation requires at run time.
viii. ReplyAction - specifies the action of the reply message for the operation.

f. WebGet attribute indicates that a method can retrieve values from Web. WebGet is used for the operations having HTTP GET verb. It has following properties –

i. BodyStyle – format of message body; wrapped or bare
ii. RequestFormat – the format of input message; JSON or XML
iii. ResponseFormat – the format of output message; JSON or XML
iv. UriTemplate – the URI for the resource to be accessed

g. WebInvoke attribute indicates that a method can be invoked by Web. Web invoke is used for the operations having HTTP POST, PUT, or DELETE verbs. It has following properties –

i. BodyStyle – format of message body; wrapped or bare
ii. Method – the HTTP verb used in the operation; POST, PUT, GET, DELETE
iii. RequestFormat – the format of input message; JSON or XML
iv. ResponseFormat – the format of output message; JSON or XML
v. UriTemplate – the URI for the resource to be accessed

7. The MytestService.svc file is a markup file which will contain the information about the service which will look like –

<%@ ServiceHost Language="C#" Debug="true" Service="MyCloudApp_WebRole.MyTestService" CodeBehind="MyTestService.svc.cs" %>  

8. The MyTestService.svc.cs file will have the implementation of the methods defined in the interface class IMyTestService.cs which will look like –

namespace MyCloudApp_WebRole
{
    // NOTE: If you change the class name "MyTestService" here, you must also update the reference to "MyTestService" in Web.config.
    public class MyTestService : IMyTestService
    {
        void CreatePoll(MyCloudApp_WebRole.Poll poll)
        {
            // write code to create poll
        }

        MyCloudApp_WebRole.Poll GetPollbyId(string pollId)
        {
            // write code to Get poll details based on input poll ID
        }
    }
}

Even consuming a service on Azure is almost same as consuming a service in on-premises application. We’ll have a look on how the REST based WCF Service can be consumed by a client asynchronously using  WebClient –

1. Write the following code when CreatePoll service method is to be called –

// take user input for poll creation and save it in Poll entity object

// since data contract cannot be exposed to client directly, create a string called xmlString by serializing Poll entity object

// create service URI and web client
string strUri;
if (current.Request.UserHostName == "127.0.0.1")
{
    // URI for running the project on dev fabric
    strUri = "http://" + current.Request.Url.DnsSafeHost + ":" + Request.Url.Port.ToString() + "/MyTestService.svc/Poll";
}
else
{
    // URI for hosted environment
    strUri = "http://" + current.Request.Url.DnsSafeHost + "/MyTestService.svc/Poll";
}
            
           
Uri uri = new Uri(strUri);
WebClient client = new WebClient();
client.Headers["Content-Type"] = "text/plain";

The highlighted text above is for us to be able to figure out whether the code is being executed from the dev fabric or from the Azure environment. [Additional step for Azure Projects]

2. Call the service asynchronously using UploadStringAsync to POST the data to create the poll to the service

// send the string to specified resource asynchronously 
client.UploadStringAsync(uri, xmlString);  
// Create the handler to be called when upload is completed 
client.UploadStringCompleted += new UploadStringCompletedEventHandler(PollUploadCompleted); 

3. Create the handler and write code to be called after upload completion

void PollUploadCompleted(object sender, UploadStringCompletedEventArgs e)
{
      // write code to perform operations after upload completion like poll creaion message to user etc.
}

4. To call GetPollbyId service method with GET operation, follow the step 1 mentioned above with modified URI for the method

// get the pollID for which poll details are to be fetched

// create service URI and web client
string strUri;
if (current.Request.UserHostName == "127.0.0.1")
{
    // URI for running the project on dev fabric
    strUri = "http://" + current.Request.Url.DnsSafeHost + ":" + Request.Url.Port.ToString() + "/MyTestService.svc/Poll/Id/" + pollId;
}
else
{
    // URI for hosted environment
    strUri = "http://" + current.Request.Url.DnsSafeHost + "/MyTestService.svc/Poll/Id/" + pollId;
}
            
           
Uri uri = new Uri(strUri);
WebClient client = new WebClient();

[Additional step for Azure Projects]

5. Call the service asynchronously using DownloadStringAsync to GET the poll details for a given poll ID

// download string from the specified URI  
client.DownloadStringAsync (uri);  
// Create the handler to be called when download is completed  
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(PollDownloadCompleted);   

6. Create the handler and write code to be called after download completion

void PollDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
{
      // write code to perform operations after download completion like displaying poll details.
}

After following the steps above, we can conclude that creating a RESTful WCF service on Azure is almost same as creating an on-premise RESTful WCF service.

TrackBack

TrackBack URL for this entry:
http://www.infosysblogs.com/apps/mt-tb.cgi/2019

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Please key in the two words you see in the box to validate your identity as an authentic user and reduce spam.

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter