Click here to Skip to main content
15,861,168 members
Articles / Web Development / IIS

Build ReST based Web Services in .NET/C#

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
12 Jul 2009CPOL2 min read 121.5K   5.5K   55   19
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:

XML
<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:

C#
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:

C#
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:

C#
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)


Written By
United States United States
Loves coding...

Comments and Discussions

 
GeneralHosting in Windows Service Pin
vanjaESS25-Jan-11 6:08
vanjaESS25-Jan-11 6:08 
GeneralMy Vote of 5 Pin
Sluggish14-Dec-10 10:15
Sluggish14-Dec-10 10:15 
QuestionSIX different classes = simple??? Pin
moonfly33322-Sep-10 13:35
moonfly33322-Sep-10 13:35 
AnswerRe: SIX different classes = simple??? Pin
AdamNThompson28-Jan-12 16:57
AdamNThompson28-Jan-12 16:57 
GeneralAny body knows Pin
robertox200422-Jul-10 23:12
robertox200422-Jul-10 23:12 
AnswerRe: Any body knows Pin
thatraja10-Aug-10 21:21
professionalthatraja10-Aug-10 21:21 
GeneralCannot deploy in IIS 7 Pin
TillmanZ23-Feb-10 19:32
TillmanZ23-Feb-10 19:32 
Hi there,

running the solution in VStudio 2010 (with the built in cassini web server) works great and just as I have hoped.
However when I deploy the project into IIS7 (create Web-Site and point to folder where the default.aspx and the bin directory are located) it will not work.
More precisely the RestServiceHandler is never being called. I have added some debug prints and all I get is nothing. Smile | :)
So what do I need to do in order for IIS 7 to really start using the code?

By the way - I have modified the web.config accordingly. So it currently has two entries with "add verb path="RestService/*" and the other with "add verb path="RestService/*/*".

Again, everything works fine locally in VStudio only IIS7 does not want to jump into the code.

Thank you very much for your support!


Cheers
GeneralAssigning Session ID REST Web Service Pin
Member 116029618-Feb-10 6:02
Member 116029618-Feb-10 6:02 
GeneralProblem in deploying REST service in IIS Pin
jimmyjos16-Oct-09 2:02
jimmyjos16-Oct-09 2:02 
GeneralRe: Problem in deploying REST service in IIS Pin
mdodich18-Nov-09 8:40
mdodich18-Nov-09 8:40 
GeneralRe: Problem in deploying REST service in IIS Pin
Rafael Ferraro18-Jan-10 8:33
Rafael Ferraro18-Jan-10 8:33 
GeneralRe: Problem in deploying REST service in IIS Pin
mdodich19-Jan-10 3:05
mdodich19-Jan-10 3:05 
GeneralRe: Problem in deploying REST service in IIS Pin
____11-Feb-10 12:44
____11-Feb-10 12:44 
Generaldirectly aceesing using URL in IE Pin
raam_kimi26-Aug-09 2:20
raam_kimi26-Aug-09 2:20 
GeneralRe: directly aceesing using URL in IE Pin
raam_kimi26-Aug-09 2:24
raam_kimi26-Aug-09 2:24 
QuestionIIS7 Pin
Kofi Sarfo13-Jul-09 20:32
Kofi Sarfo13-Jul-09 20:32 
AnswerRe: IIS7 Pin
Parag.Gadkari14-Jul-09 17:12
Parag.Gadkari14-Jul-09 17:12 
GeneralRe: IIS7 PinPopular
MichaelMerrell30-Jul-09 3:48
MichaelMerrell30-Jul-09 3:48 
GeneralRe: IIS7 Pin
mamidrx11-May-12 8:47
mamidrx11-May-12 8:47 

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

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