Jon Flanders' Blog

Using WCF WebHttpBinding and WebGet with nicer Urls

Saturday, August 18, 2007 7:39:26 PM (GMT Standard Time, UTC+00:00)

I've been playing with the REST support in .NET 3.5.  I'm really enjoying the programming model, but I am not enjoying the .svc file extension in my URLs (I'm not the only person I know who has felt this way for quite some time).

IMO (from what little I know about the REST style) URLs shouldn't have things like extensions in them (or preferably not).  So with they way WCF endpoint hosting in IIS works (obviously if I am hosting a webHttpBinding in a non-IIS host I can totally control the URLs, but I am writing a REST API to something where I plan to be hosting inside of IIS).  This would end up being my url:

http://host/albumn.svc/instance/

and I want:

http://host/albumn/instance/

The .svc extension in the URL doesn't seem opaque to me.  I tried modifying the HttpHandler element for the svc file - but that didn't work for various reasons.  So I ended up writing a simple HttpModule to do URL re-writing (using HttpContext.RewritePath).  I didn't really want any config relating to URLs - so this module assumes you are serving up only REST based URLs from a web application.  If you were going to use it and serve up other handlers (like aspx files etc) it would need to be modified. Here is the module code:

public class RestModule : IHttpModule
{


public void Dispose()
{ }

public void Init(HttpApplication app)
{
app.BeginRequest += delegate
{
HttpContext ctx = HttpContext.Current;
string path = ctx.Request.AppRelativeCurrentExecutionFilePath;

int i = path.IndexOf('/', 2);
if(i>0)
{
string svc = path.Substring(0, i) + ".svc";
string rest = path.Substring(i, path.Length - i);
ctx.RewritePath(svc, rest, ctx.Request.QueryString.ToString(), false);
}
};

}


}

After configuring this in my web.config - I have the ability to type:

http://localhost/RestTest/Service2/Test?id=9999

and the module will translate it to Service2.svc as the handler file - which makes WCF happy.

If you are interested you can download the code here:

RestTest.zip (3.71 KB)

EDIT:  Christian pointed out that this approach alone will not work in IIS6 (my approach is for integrated mode of IIS7).  For IIS you have to add aspnet_isapi.dll to the Wildard Application Maps.  But then he goes on to tell me no one will do that ;-).  So I say - good reason to move to IIS7 and Longhorn/Windows 2008 - since it has a go-live license.

 |    #    Comments [5]   

Saturday, August 25, 2007 7:04:39 AM (GMT Standard Time, UTC+00:00)
What's wrong with wildcard mappings? They are scoped by application and with .NET 2+/IIS6 they keep the performance impact as low as possible.

Good work Jon!
Friday, August 31, 2007 9:13:00 PM (GMT Standard Time, UTC+00:00)
Or, you could use a rewrite filter, like IIRF
http://www.codeplex.com/IIRF
Thursday, October 25, 2007 10:49:22 PM (GMT Standard Time, UTC+00:00)
Hi Dino -sorry I didn't your comment before now - I wouldn't want to use a filter - since IIS7 has the managed pipline - I wouldn't want to invest in maintaining unmanaged code.
Thursday, November 15, 2007 12:06:53 AM (GMT Standard Time, UTC+00:00)
Does this work on Cassini? I downloaded the sample and tried it and it doesnt seem to work. I have a breakpoint in the init function in RestTest.RestModule, but it never hits the breakpoint.

Any ideas?
Thursday, November 15, 2007 12:08:29 AM (GMT Standard Time, UTC+00:00)
Yes - it absolutely works in Cassini. Do you have the <httpModule> element setup correctly?
All comments require the approval of the site owner before being displayed.
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Navigation

Books

Courses

Search

Subscribe

  • RSS 2.0
  • Add to Windows Live button
  • Add to Google button
  • Add to MyMSN button
  • Add to MyYahoo button
  • Add to Bloglines button
  • Add to Newsgator button