Click here to Skip to main content
Click here to Skip to main content
Go to top

Build ReST based Web Services in .NET/C#

, 12 Jul 2009
Rate this:
Please Sign up or sign in to vote.
A ReST based Web Service for C#.

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 Wink | ;-) .

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)

Share

About the Author

Parag.Gadkari

United States United States
Loves coding...

You may also be interested in...

Comments and Discussions

 
GeneralHosting in Windows Service PinmembervanjaESS25-Jan-11 6:08 
GeneralMy Vote of 5 PinmemberSluggish14-Dec-10 10:15 
QuestionSIX different classes = simple??? Pinmembermoonfly33322-Sep-10 13:35 
AnswerRe: SIX different classes = simple??? PinmemberAdamNThompson28-Jan-12 16:57 
GeneralAny body knows Pinmemberrobertox200422-Jul-10 23:12 
AnswerRe: Any body knows Pinmemberthatraja10-Aug-10 21:21 
GeneralCannot deploy in IIS 7 PinmemberTillmanZ23-Feb-10 19:32 
GeneralAssigning Session ID REST Web Service PinmemberMember 116029618-Feb-10 6:02 
GeneralProblem in deploying REST service in IIS Pinmemberjimmyjos16-Oct-09 2:02 
GeneralRe: Problem in deploying REST service in IIS Pinmembermdodich18-Nov-09 8:40 
GeneralRe: Problem in deploying REST service in IIS PinmemberRafael Ferraro18-Jan-10 8:33 
GeneralRe: Problem in deploying REST service in IIS Pinmembermdodich19-Jan-10 3:05 
GeneralRe: Problem in deploying REST service in IIS Pinmembergoldlaser11-Feb-10 12:44 
Generaldirectly aceesing using URL in IE Pinmemberraam_kimi26-Aug-09 2:20 
thanks for the great articel..
i can be able to access the rest service by just passing this URL in IE http://localhost:1055/RESTService/Parts.. but how do i invoke the SUM method in calculator...
 
is that possible..?
 
Thanks
Ramesh Vel
 
Its Just Zeros and Ones

GeneralRe: directly aceesing using URL in IE Pinmemberraam_kimi26-Aug-09 2:24 
QuestionIIS7 PinmemberKofi Sarfo13-Jul-09 20:32 
AnswerRe: IIS7 PinmemberParag.Gadkari14-Jul-09 17:12 
GeneralRe: IIS7 PinmemberEldiablohijo30-Jul-09 3:48 
GeneralRe: IIS7 Pinmembermamidrx11-May-12 8:47 

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.

| Advertise | Privacy | Mobile
Web03 | 2.8.140926.1 | Last Updated 12 Jul 2009
Article Copyright 2009 by Parag.Gadkari
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid