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

This article describes how to cheat your way to an elegant URL REST Web service.

Notes

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.

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.

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:

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.

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 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.

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.

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.

Share

About the Author

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.

Good tips. I got the name of the section in IIS7 from some other article, one about handlers probably. I still don't think I've ever used IIS7 (although the days are numbered when that will continue to be the case we're about to move to brand new servers where I am).

The Reg Exp thing is very nice. I love RegEx as well despite what mean people saying that if you have a problem and RegEx is the answer you now have two problems...

And your webservices are instantly RESTful (and still support SOAP 1.2). Even the response is stripped of the enclosing SOAP envelope.

So, why do what your article suggests, when this easier option is available? Is there some pros/cons I'm missing? Or some aspect of RESTful webservices that the above web.config setting doesn't give you?

So, it looks to me like the request is formatted the way you wanted. Do you see anything, umm... un-RESTful here?

You'll notice that the response strips out the soap envelop parent. This is a bit surprising to me. Since it is SOAP 1.2, I would have expected the HTTP GET to return a SOAP formatted response. Apparently, the "HttpGet" protocol trick in web.config file decides that if you use HTTP GET, you want REST and formats it accordingly. But that still seems like an odd assumption on .NET's part.