Click here to Skip to main content
Click here to Skip to main content

REST Web Services in ASP.NET 2.0 (C#)

, 5 Nov 2008
Rate this:
Please Sign up or sign in to vote.
This article describes how to cheat your way to an elegant URL REST Web service.

Notes

  1. I have been informed that in .NET 3.5, there are smoother ways to do this. I do say that later in the article, but please be aware that this is a 2.0 only workaround. 
  2. I have had a warning that IIS6.0 doesn't like this workaround. I have only tried it on IIS 5.1 and it seemed fine. I shall be doing more testing when I can and I will let you know the results. RESULTS both IIS 6.0 and 5.1 require some tinkering to read URLs with no file extension. The 6.0 process can be found in the comments to this article. The 5.1 version requires the following steps: 
    • Open the website properties in IIS
    • Select the Home tab
    • Click the Configuration button
    • In new window select the Mappings tab
    • Click the Add button
    • In new window's executable field Browse to the ASP.NET ISAPI DLL (usually something like C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll)
    • In the Extension field, type .*
    • Untick the Check that file exists box and click OK 

N.B. There is a bug that if your OK button is not active, you need to click the executable field text box, you should see the middle section of the text in the box change from /.../ to the full file path.This should now make the OK button active.

Thanks to Neil Kilbride for that.

Introduction

Like so many people, I started out using SOAP Web requests which do integrate nicely into an IDE but they're not intuitive to the internet generation. A lot of people, Yahoo is one example, want their services to work in a way that any idiot could interpret or predict a likely behaviour. After all, if there's one thing you know you'll find on the internet it's any idiot.

So instead of pitching a great ball of SOAP to a server which then spits its own ball of SOAP back at you, we're going to take a look at REST.

If you really have to know REST stands for: Representational State Transfer.

I bet you feel better knowing that.

No. Maybe not.

I often find there's a dearth of brass tacks answers in Internet tutorials so if you've got this far I'll guess you are either familiar with or amenable to a Web request that is formatted...

www.someserviceprovider.com/myrestservice/3

... and which returns some handy chunk of XML or similar.

Yes. A REST request, when all is said and done, is a service which replaces your SOAP suds with a simple, common or garden URL.

It also just returns some XML or formatted text or whatever instead of a matching SOAP bubble. What could be simpler, put a URL into your address bar and unearth some juicy content.

Well, although it *is* simple from a user perspective, learning how to actually do it is another problem altogether.

What you're looking to do is implement an interface called IHttpHandler and the easiest way to get a working stub for this is to go to a Web project and add a new item of type generic handler (*.ashx file extension). When you do so, it will return a blank service that looks like this:

<%@ WebHandler Language="C#" Class="example" %>

using System;
using System.Web;

public class exampleRestService : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

Basically you add your code into the "ProcessRequest" method and it can write something back to the screen, be that (as in this case) some text, or an XML document or whatever using its HttpContext object. As with any plain Web Request, what you submitted in the URL is a GET request and the only difference between this and visiting a website is that you are not requesting a file, you are requesting the current state of an object (i.e. a service).

However when you are using a generic handler harness the URL you would use to access it would be along the lines of:

www.someserviceprovider.com/exampleRestService.ashx

And it would do the rest.

So that is blatantly referring to a file, which is not as elegant as what we're wanting to do by implying in the very structure of our URL that there is no actual file to which we are referring.

However, while we have this acceptable yet clunky beast in front of us, let's make it do something when you prod it because it's easier to get your head round at this stage.

<%@ WebHandler Language="C#" Class="example" %>

using System;
using System.Web;

public class exampleRestService : IHttpHandler {
    
    public void ProcessRequest (HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        string output = "";

        if (context.Request["input"] != null)
        {
                output = context.Request.QueryString["input"].ToString();
        	context.Response.Write("Your Input Was: " + output);
        }
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

This basically means that when someone visits:

www.someserviceprovider.com/exampleRestService.ashx?input=hello%20world

Then the response they will get will be:

Your Input Was: hello world

So the effect is all great, but the execution leaves a little something to be desired. How do we grasp that subtly more pleasing URL format we were initially after?

The first thing you're going to have to do is start mucking about with your web.config file. The section you need differs depending on whether your IIS is 6.0 backwards or 7.0. If the latter, you're looking for a section called < handlers > in the < system.web > section. If the former, the section is in the same parent location but is now called < httpHandlers >.

The entry you want to put into the section looks like this:

IIS 6.0 and previous: <add type="MyWebServices.exampleRestService, 
	MyWebServices" path="exampleRestService/*" verb="*">

IIS 7.0: <add type="MyWebServices.exampleRestService, 
	MyWebServices" path="exampleRestService/*" verb="*" 
	name="exampleRestService">

The important attribute of this tag for our purposes is the one marked "type". Briefly I'll run through the rest: verb= will this be a handler for just GET? just POST? or both (*) so this one is both; path= what is the domain looking for in rerouting to this service? In this case, the path "exampleRestService/" and then anything from nothing to a single character to the text of your latest hilarious internet memo received via email (because even IIS needs a good laugh occasionally).

But then we get to the type attribute (Oh, IIS 7 people I don't run IIS 7 so what the name attribute does I'm not exactly clear on... names it? For some no doubt a wonderful benefit, I imagine.) What does it do? What magic does it perform? Well the first part before the comma tells it what namespace to look for and what class in that namespace it is trying to find. The part after the comma refers to the assembly it's going to look at.

I can see you all telling me to back up a few places here.

What assembly? I hear you ask. The one you are about to create I answer.

You see to do the URL handling you can't use the *.ashx file, it has to go. Sorry. Instead what you are going to do is start a new C# class library project. And for consistency with this article, you might call it MyWebServices.

Then in your class library, you might want to call your class exampleRestService.cs.

And it will look like this:

using System;
using System.Web;

namespace MyWebServices
{
 public class exampleRestService : IHttpHandler {
    
    public void ProcessRequest (HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        string output = "";

        if (context.Request["input"] != null)
        {
                output = context.Request.QueryString["input"].ToString();
        	context.Response.Write("Your Input Was: " + output);
        }
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
 }
}

Yes, basically the ASHX without the ASP.NET header. Exactly.
Compile this out to a convenient location and then back in your Web project create a reference to the DLL you just compiled.

Now it all becomes clear, yes?

Well, no.

Because you'll still notice that to get the correct output, the URL has to be:

www.someserviceprovider.com/exampleRestService/?input=hello%20world

So close... yet not quite close enough.

We're literally "?input=" away from our goal. This problem would seem to be intractable. Apparently in .NET 3.5 or whatever the cool kids are calling it these days, there's some way of taking care of this automatically. I don't know, I'm still using 2.0.

All I know is that the probable best way to deal with this is to cheat.

Yes, you heard me. Cheat.

We all know that if you have input for a dynamic Web page, it should come in the form of GET or POST variables. That's fine but GET variables are always behind that dratted "?" and then you need each one to be tagged with a name like input which then "=" whatever you want to send.

If you have only one input variable, there's a way around this.

And here it is:

string output = "";
int subPos = 0;

output = context.Request.RawUrl.ToString();
if(output.IndexOf("/exampleRestService/") > -1)
{
        subPos = output.IndexOf("/exampleRestService/");
        subPos = subPos + 20;
	output = output.Substring(subPos);
}

context.Response.Write("Your Input Was: " + output);

Not exactly the most robust of solutions but, trust me, it works. It could be that you tuned out on me way back after I told you to start making class libraries and the like, but maybe you want to go that extra mile. If so, this is a way. I'd be keen to hear any better ideas as I'm not sure how robust this one would be in the long term.

For now though...

www.someserviceprovider.com/exampleRestService/the%20end

... will tell you that:

Your Input Was: the end 

License

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

About the Author

Leo Stableford
Web Developer
United Kingdom United Kingdom
Leo Stableford has been working in IS for seven years. Initially as a teacher and then for the last five years as in-house developer for an eclectic variety of private sector organisations from law firms to concert ticket agencies.
 
He started out working in Classic ASP and moved to .Net three years ago. His .Net language of choice is C# and he also develops a fair bit of T-SQL for SQL Server 2005 and PHP with MySQL.
 
He lives in Nottingham and has only just started coding for pleasure. He understands this is a slippery slope.

Comments and Discussions

 
QuestionNice article PinmemberClivest27-Jun-11 12:19 
AnswerRe: Nice article PinmemberLeo Stableford27-Jun-11 21:55 
GeneralGreat help PinmemberPratiPhil5-Apr-11 4:00 
GeneralVerb type PUT and DELETE on IIS7 anonymous web Pinmembermjehle11-Dec-09 4:27 
Generalvery helpful article Pinmember$unil Dhiman28-Oct-09 23:32 
GeneralSOAP 1.2 and web.config PinmemberDean Hallman21-May-09 0:44 
QuestionRe: SOAP 1.2 and web.config PinmemberLeo Stableford21-May-09 1:45 
AnswerRe: SOAP 1.2 and web.config PinmemberDean Hallman21-May-09 6:34 
GeneralAlso visit this link for more info: http://softwareprogramminghelp.blogspot.com/ Pinmemberdesaivishal112-Mar-09 14:56 
Questionreading REST requests? Pinmemberfetlock23-Oct-08 4:21 
GeneralHello again, Leo. Sorry, I may have to revise my rating... PinmemberMMCompton2-Oct-08 10:18 
GeneralRe: Hello again, Leo. Sorry, I may have to revise my rating... PinmemberLeo Stableford2-Oct-08 21:53 
GeneralRe: Hello again, Leo. Sorry, I may have to revise my rating... PinmemberMMCompton3-Oct-08 8:33 
QuestionRe: Hello again, Leo. Sorry, I may have to revise my rating... Pinmemberiamstarbuck1-Jun-09 22:13 
AnswerRe: Hello again, Leo. Sorry, I may have to revise my rating... PinmemberLeo Stableford13-Apr-10 0:36 
QuestionHi Leo, good article [modified] PinmemberMMCompton2-Oct-08 9:12 
QuestionRe: Hi Leo, good article PinmemberBarry180324-Nov-09 7:46 
GeneralNice but... PinmemberJacobs7629-Sep-08 21:33 
GeneralRe: Nice but... PinmemberLeo Stableford29-Sep-08 21:38 
GeneralRe: Nice but... PinmemberJacobs7629-Sep-08 21:48 
GeneralRe: Nice but... PinmemberLeo Stableford29-Sep-08 21:57 
JokeRe: Nice but... PinmemberRed Feet1-Oct-08 4:51 

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
Web04 | 2.8.140721.1 | Last Updated 5 Nov 2008
Article Copyright 2008 by Leo Stableford
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid