Rest ASP.NET Example
This page describes how to get an ASP.NET application to work with the PUT and DELETE verbs under IIS on Windows XP Professional. Other versions of IIS / Windows may vary in configuration, but the process should be almost identically.
IIS configuration
-
Open up the IIS configuration manager. Click the [Properties]-button on the web application that should support the PUT and DELETE verbs.
-
On the Directory tab, click the [Configuration]-button.
-
On the Mappings tab, find the .aspx extension and click the [Edit]-button.
-
In the Verbs section, either check All Verbs or add PUT and DELETE to the comma-separated list in Limit to: and keep this one checked.
-
Click [OK] in all the windows.
File system configuration
-
Find the folder you need PUT and DELETE access to in Windows Explorer.
-
Right click the folder and chose Properties.
-
Go to the Security tab and click the [Add] button.
-
Make sure that the Location is correct. Chose location with the [Location]-button. It should be your local machine.
-
Write IUSR_<your_machine_name> into the textbox, e.g. IUSR_ASBJORNPC and click the [OK]-button.
-
Give IUSR_<your_machine_name> Write permission by checking the proper checkbox in the Allow column.
-
Click the [OK]-button
The requesting webform
VerbTest1.aspx
<%@ Page language="C#" Codebehind="VerbTest1.aspx.cs" AutoEventWireup="false" Inherits="VerbTest1" %>
VerbTest1.aspx.cs
using System; using System.Net; using System.IO; public class VerbTest1 : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { Response.ContentType = "text/plain"; const string data = "<feed><title>Hello!</title></feed>"; HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create("http://localhost/test/verbtest2.aspx"); req.ContentType = "multipart/form-data; charset=ISO-8859-1"; req.Method = "PUT"; StreamWriter sw = new StreamWriter(req.GetRequestStream()); sw.Write(data); sw.Close(); HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); using (resp) { StreamReader sr = new StreamReader(resp.GetResponseStream()); Response.Write(sr.ReadToEnd()); sr.Close(); resp.Close(); } } override protected void OnInit(EventArgs e) { InitializeComponent(); base.OnInit(e); } private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } }
The receiving webform
Using System.Web.IHttpHandler
Note: IHttpHandler may be a better choice than System.Web.Page for the receiver. Using System.Web.Page may incur unnecessary overhead. See for example, this article on using Custom Http Handlers To Improve Performance in ASP.NET.
VerbTest2.ashx
<%@ webhandler language="C#" class="Sample.VerbHandler" %> using System; using System.Web; namespace Sample { public class VerbHandler : IHttpHandler { public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext ctx) { switch (ctx.Request.HttpMethod) { case "DELETE": ProcessDelete(ctx); break; case "GET": ProcessGet(ctx); break; case "PUT": ProcessPut(ctx); break; case "POST": ProcessPost(ctx); break; } } } public virtual void ProcessGet(HttpContext ctx) { ... } public virtual void ProcessPut(HttpContext ctx) { ... } public virtual void ProcessPost(HttpContext ctx) { ... } public virtual void ProcessDelete(HttpContext ctx) { ... } }
Using System.Web.Page
VerbTest2.aspx
<%@ Page language="c#" Codebehind="VerbTest2.aspx.cs" AutoEventWireup="false" Inherits="VerbTest2" %>
VerbTest2.aspx.cs
using System; using System.Net; using System.IO; public class VerbTest2 : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { Stream stream = Request.InputStream; StreamReader sr = new StreamReader(stream); Response.Write(sr.ReadToEnd()); } override protected void OnInit(EventArgs e) { InitializeComponent(); base.OnInit(e); } private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } }
Discussion
[MartinAtkins] Has anyone managed to get a PUT to a 'real URL' to work in IIS? By this, I mean not PUTting directly to the URL of the script which will handle it, but rather PUTting (or DELETEing) to a URL which reflects what is to be PUT or DELETEd. A comparable term in Apache would be "extra path information". (Feel free to refactor/remove this. I put it here for want of a better place.)
[AsbjornUlsberg] This can be easilly accomplished by configuring the IIS web application to give all HTTP requests to the ASP.NET framework, and then, in Global.asax.cs, plug in a little rewrite-code. See URL Rewriting with ASP.NET for more information.
[MartinAtkins] Well, I guess I meant to post this to the example for plain old ASP, not ASP.NET. Since you're dealing with both, and the results of this discussion will hopefully be refactored elsewhere at some point, I'll just ask here to avoid making a lot of noise: I can see how a similar technique could be used to map everything to the plain old ASP ISAPI extension, but does it have the URL rewriting thing?
[AsbjornUlsberg] If I'm not totally lost, rewriting plain old ASP can also be done in ASP.NET. If I'm lost or ASP.NET isn't available, it must be done with the dreadful ISAPI filters, yes.
[MartinAtkins] I'll also note that this requires special server configuration, which I'm assuming most users whose sites live on other people's Windows servers will not be able to change.
[AsbjornUlsberg] Special server configuration will be required in almost all cases, but it's probably more likely that Apache users will have access to it than IIS users, yes.
[KenMacLeod] The URL rewriting/"real" URL/PATH_INFO question and answer appear to be talking about different things. This goes to the note in CarrorVsOrange: if the ASP script is "at a URL" that accepts GET/POST, can not that same script "at that URL" also accept additional path information after the script? By comparison, in the CGI spec (both IIS and Apache), that "extra path information" comes in the PATH_INFO environment variable.
POST /path/to/my.asp PUT /path/to/my.asp/with/extra/path/info
[AsbjornUlsberg] The latter example isn't possible in traditional ASP, but it is in ASP.NET. To get the /with/extra/path/info portion of the request, you can use Request.PathInfo.
[KenMacLeod] In that context (ASP-only, refactoring requested), can you confirm or further describe what the URL-space will look like for the publishing system? I'm guessing if it's not using PathInfo, it'll be using URL query arguments or similar:
PUT /path/to/my.asp?entry=4328 DELETE /path/to/my.asp?comment=321
[AsbjornUlsberg] URL queries work, of course. You can also pass an ad hoc PathInfo to the ASP script if you add a question mark before it, like this:
POST /path/to/my.asp PUT /path/to/my.asp?/with/extra/path/info
If the script isn't separated from the query/PathInfo with a question mark, IIS won't understand what script is to be accessed and can't find the path, so it throws a 404. When separated like above, the PathInfo can be received with Request.QueryString in the ASP script.
[KenMacLeod] I'm not familiar with either IIS or ASP[.NET], so I'm drawing a parallel from Apache and CGI:
-
Is the IIS configuration above required for all ASP or CGI, or just ASP? On Apache, the CGI handler allows all methods and PATH_INFO by default.
-
[AsbjornUlsberg] I haven't tried CGI on IIS, so I don't know, really. But as everything in IIS is handled through ISAPI, I don't think theres much difference between ASP and CGI, unless the CGI implementation is an ASAPI filter. PHP can be installed as both an ASAPI filter and CGI on IIS, afaik, and I believe the ASAPI version will function more natively than the CGI one. But I don't really know.
-
[KenMacLeod] Why is write permission required in the file system? Just making sure there's not a miscommunication: on the one hand, PUT/DELETE aren't necessarily going to a file system in all cases (they could be going to a database, for example), on the other hand, a POST-based ASP could possibly write to the filesystem, would this filesystem change be required in that case?
-
[AsbjornUlsberg] Yes, when I fiddeled with this, write permission was required, but only for ASP.NET -- not for traditional ASP. I guess this is a security setting in ASP.NET, and it's possible that it can be configured in Web.Config (ASP.NET's equivalence to .htaccess), but I haven't explored this any further as I believed the filesystem permissions were easy enough to set.
Original Author: AsbjornUlsberg