Click here to Skip to main content
Licence CPOL
First Posted 12 Jul 2009
Views 37,463
Downloads 1,495
Bookmarked 44 times

Build ReST based Web Services in .NET/C#

By Parag.Gadkari | 12 Jul 2009
A ReST based Web Service for C#.

1

2

3

4
10 votes, 100.0%
5
5.00/5 - 10 votes
μ 5.00, σa 1.10 [?]

Introduction

There are various examples of ReST available on the net like Web-Services for .NET/C#, but none of them provide a simple .NETish framework. For example, how easy is it to create a Web-Service by just deriving from a class and annotating methods as exposed for the web? This article provides a small framework for ReST based Web-Services primarily targeted for .NET versions 3.5 and older.

Using the code

Like any other article on the web about ReST and .NET, this implementation involves handling specific resources request through an IHttpHandler; in this case, it is PoC.Web.Services.ReSTServiceHandler. This IHttpHandler would handle the ReST calls (Get, Put, Post, and Delete) and dispatch them appropriately. In order to add the handler, the following lines must be added to the web.config:

<system.web>
    ....
    ....
    <httpHandlers>
        ....
        <add verb="*" path="RESTService/*" 
          type="PoC.Web.Services.ReSTServiceHandler, PoC.Web.ReSTService"/>
        <add verb="*" path="RESTService/*/*" 
          type="PoC.Web.Services.ReSTServiceHandler, PoC.Web.ReSTService"/>
    </httpHandlers>
</system.web>

The library provides two mechanisms for ReST Web-Services:

  1. IReSTService
  2. Same as the Web-Service model. Annotate all the methods of a class which need to be exposed.

  3. IReSTFulService
  4. Provides four calls to handle a request: Get, Put, Post, and Delete.

IReSTService based Web-Service

An example of an IReSTService is shown below:

public class Calculator : PoC.Web.Services.IReSTService
{
    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    public int Sum(int a, int b)
    {
        return a + b;
    }
    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    public int Multiply(int a, int b)
    {
        return a * b;
    }
    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    public int Subtract(int a, int b)
    {
        return a - b;
    }
}

In this example, we have a Calculator class which implements IReSTService and exposes three methods by annotating them with the ReSTMethod attribute. The ReSTMethod attribute requires an allowed verb on that method. That's it. If built, the CalculatorService can now be accessed by these URLs:

  1. Sum URL: http://<servername/localhost>/<web app>/RESTService/Calculator/Sum?a=-1&b=2
  2. Multiply URL: http:/<servername/localhost>/<web app>/RESTService/Calculator/Multiply?a=195&b=21
  3. Subtract URL: http:/<servername/localhost>/<web app>/RESTService/Calculator/Subtract?a=-12&b=2

Here is another example:

public class ShowNTell : PoC.Web.Services.IReSTService
{
    XmlDocument dom = new XmlDocument();
    public ShowNTell()
    {
        dom.LoadXml("<Root><Child><SubChild>" + 
                    "<Parameter></Parameter><MagicNumber>" + 
                    System.Guid.NewGuid().ToString("N") + 
                    "</MagicNumber></SubChild>" + 
                    "</Child></Root>");
    }
    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    [PoC.Web.Services.ReSTXmlResponse]
    public Employee[] Object2Xml()
    {
        Employee e1 = new Employee();
        e1.Name = "Aremac Nokin ";
        e1.Id = "11201";
        e1.Address = "123 Summer Drive";
        e1.City = "Brahman";
        e1.Zip = "00001";
        e1.JoiningDate = DateTime.Today.AddYears(-5).AddMonths(-3).AddDays(-20);
        e1.Salary = 100000.00;
        Employee e2 = new Employee();
        e2.Name = "Reyalp Sinnet";
        e2.Id = "11201";
        e2.Address = "123 Summer Drive";
        e2.City = "Brahman";
        e2.Zip = "00001";
        e2.JoiningDate = 
          DateTime.Today.AddYears(-2).AddMonths(-1).AddDays(-40);
        e2.Salary = 200000.00;
        return new Employee[] { e1, e2 };
    }
    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    public XmlNode ReturnNode(string some_param)
    {
        dom.SelectSingleNode("//Root/Child/SubChild/Parameter").InnerText = some_param;
        return dom.SelectSingleNode("//Root/Child/SubChild");
    }

    [PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
    public XmlDocument ReturnDom(XmlDocument param_1, int param2)
    {
        dom.SelectSingleNode("//Root/Child/SubChild/Parameter").InnerText = 
                             param2.ToString();
        if (param_1 != null && param_1.DocumentElement != null)
        {
            XmlElement elem = dom.CreateElement("NewItem");
            elem.InnerXml = param_1.DocumentElement.OuterXml;
            dom.SelectSingleNode("//Root/Child").AppendChild(elem);
        }
        return dom;
    }
}

In this example, we are exposing an array of POCO, an XmlNode, and an XmlDocument. We also see a new attribute in this example, ReSTXmlResponse. This attribute makes the engine (IHttpHandler) return an XML representation of the object by serializing the object. If the return type of the method is typeof XmlNode, then the engine would return the OuterXml of the node and set the content-type to "xml". And yes, there is a special type converter for XmlDocument/XmlNode from string ;-).

IReSTFulService based Web-Service

This interface has the following methods:

  • object GetCall(string args, HttpContext context)
  • object PutCall(string args, HttpContext context)
  • object PostCall(string args, HttpContext context)
  • object DeleteCall(string args, HttpContext context)

An example is shown below:

public class Parts : PoC.Web.Services.IReSTFulService
{
    ....
    ....
    #region IReSTFulService Members

    public object GetCall(string arg, HttpContext context)
    {
        if (string.IsNullOrEmpty(arg))
        {
            
            return allParts; // typeof Parts[]
        }
        else
        {
            return filteredParts; //typeof Parts[]
        }
    }

    public object PutCall(string arg, HttpContext context)
    {
        Part ps = null;
        //Get Part
        try
        {
          ps = PoC.Web.Services.Utilities.TypeConversion.
                   Deserialize<part>(context.Request.InputStream);
        }
        catch(Exception ex){ //Bad Stream
                throw new PoC.Web.Services.InternalErrorException(503, "Bad Stream");
        }
        return UpdatePart(ps);// let's say string
    }

    public object PostCall(string arg, HttpContext context)
    {
        Part ps = null;
        //Get Part
        try
        {
            ps = PoC.Web.Services.Utilities.TypeConversion.
                    Deserialize<part>(context.Request.InputStream);
        }
        catch (Exception ex)
        { //Bad Stream
            throw new PoC.Web.Services.InternalErrorException(503, "Bad Stream");
        }
        return InsertPart(ps);

    }

    public object DeleteCall(string arg, HttpContext context)
    {
       throw new PoC.Web.Services.InternalErrorException(503, "Method Not Supported");
    }

    #endregion
}

The "Parts" service can now be accessed through the following links:

  1. Link to get all Parts:
  2. URL: http://<Servername/localhost>/<Web App name>/RESTService/Parts

    HTTP method: Get

  3. Link to get a Part by ID:
  4. URL: http://<Servername/localhost>/<Web App name>/RESTService/Parts/1101

    HTTP method: Get

  5. Update a Part:
  6. URL: http://<Servername/localhost>/<Web App name>/RESTService/Parts

    HTTP method: Put

    Send Body: '<Part><Id>1103</Id><Name>somet part name</Name><Description>something ...</Description></Part>'

  7. Create a new Part:
  8. URL: http://<Servername/localhost>/<Web App name>/RESTService/Parts

    HTTP method: Post

    Send Body: '<Part><Id></Id><Name>somet part name</Name><Description>something ...</Description></Part>'

  9. Delete a Part:
  10. URL: http://<Servername/localhost>/<Web App name>/RESTService/Parts/1103

    HTTP method: Delete

    Send Body: '<AuthorizationCode></AuthorizationCode>'

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Parag.Gadkari



United States United States

Member
Loves coding...

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralHosting in Windows Service PinmembervanjaESS7:08 25 Jan '11  
GeneralMy Vote of 5 PinmemberSluggish11:15 14 Dec '10  
QuestionSIX different classes = simple??? Pinmembermoonfly33314:35 22 Sep '10  
AnswerRe: SIX different classes = simple??? PinmemberAdamNThompson17:57 28 Jan '12  
GeneralAny body knows Pinmemberrobertox20040:12 23 Jul '10  
AnswerRe: Any body knows Pinmemberthatraja22:21 10 Aug '10  
GeneralCannot deploy in IIS 7 PinmemberTillmanZ20:32 23 Feb '10  
GeneralAssigning Session ID REST Web Service PinmemberMember 11602967:02 18 Feb '10  
GeneralProblem in deploying REST service in IIS Pinmemberjimmyjos3:02 16 Oct '09  
GeneralRe: Problem in deploying REST service in IIS Pinmembermdodich9:40 18 Nov '09  
Sounds like my problem is similar.
 
After deploying on IIS I can get here...
http://server/app/default.aspx
 
But not here...
http://server/app/RESTService/Calculator/Sum?a=-1&b=2
 
Anyone know why?
GeneralRe: Problem in deploying REST service in IIS PinmemberRafael Ferraro9:33 18 Jan '10  
GeneralRe: Problem in deploying REST service in IIS Pinmembermdodich4:05 19 Jan '10  
GeneralRe: Problem in deploying REST service in IIS Pinmembergoldlaser13:44 11 Feb '10  
Generaldirectly aceesing using URL in IE Pinmemberraam_kimi3:20 26 Aug '09  
GeneralRe: directly aceesing using URL in IE Pinmemberraam_kimi3:24 26 Aug '09  
QuestionIIS7 PinmemberKofi Sarfo21:32 13 Jul '09  
AnswerRe: IIS7 PinmemberParag.Gadkari18:12 14 Jul '09  
GeneralRe: IIS7 PinPopularmemberEldiablohijo4:48 30 Jul '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120210.1 | Last Updated 12 Jul 2009
Article Copyright 2009 by Parag.Gadkari
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid