IIS Handler for Custom Url

Recently need to setup environment for bug fix.

The client side code calling url like http://somewhere/upload/, while at the server side the url need to receives the POST request from client to perform certain actions.

We have the ready client code to send the POST request with the contents, the missing part is the receiving side, the url in server. Current code will always give us error whenever calls made to the url because the url does not exists at all. My mission today will be faking a url to receives request and output the content as a new file, so we can test the bug fix later on.

Client code: (Refer to Posting multipart/form-data Using .NET WebRequest)

private string ExecutePostRequest(
Uri url,
Dictionary<string, string> postData,
string fileMimeType
)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.AbsoluteUri);
request.Method = "POST";
request.KeepAlive = false;
string boundary = "ILikeSeperator";
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Credentials = CredentialCache.DefaultCredentials;

// Connect to server and start sending data (use POST)
Stream requestStream = request.GetRequestStream();
postData.WriteMultipartFormData(requestStream, boundary);

byte[] endBytes = System.Text.Encoding.UTF8.GetBytes("--" + boundary + "--");
requestStream.Write(endBytes, 0, endBytes.Length);
requestStream.Close();

// Get back response from server
using (WebResponse response = request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
};
}

Nothing much to say about the client code 😀

Server Code: (My works here)

The url I going to creates is http://localhost/uploadTest. We need to add a ashx handler in IIS to handle the calls into this url. The handler will create a new text file base on contents sent by client.

There are total 6 steps needed and the sequence numbers will be highlight in Bold + red colour = Number

~~~ 0 ~~~ 0 ~~~

1- First follow the must read step-by-step guides on creating handler for specific url – ASP.NET ASHX Handler

Project created follow above guide, removed unnecessary .aspx and files.

Aspx Handler Project

2- Another important step, use correct Web.config:-


<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<customErrors mode="Off"/>
<urlMappings enabled="true">
<add url="~/Default.aspx" mappedUrl="~/FileUploadHandler.ashx"/>
</urlMappings>
<compilation debug="true"/>
</system.web>
<system.webServer>
<modules>
<remove name="WebDAVModule"/>
</modules>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="StaticFile"/>
<remove name="SimpleHandlerFactory-ISAPI-2.0"/>
<remove name="WebDAV"/>
<remove name="SimpleHandlerFactory-Integrated-4.0"/>
<remove name="SimpleHandlerFactory-Integrated"/>
<add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Write" preCondition="integratedMode"/>
<add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Write" preCondition="integratedMode,runtimeVersionv4.0"/>
<add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG,PUT,DELETE" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0"/>
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read"/>
</handlers>
<security>
<authorization>
<remove users="*" roles="" verbs=""/>
<add accessType="Allow" users="*" verbs="GET,HEAD,POST,PUT,DELETE,DEBUG"/>
</authorization>
</security>
</system.webServer>
</configuration>

3- The core of the handler code inside FileUploadHandler.ashx:


public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");

// Read input
string requestContent = new StreamReader(context.Request.InputStream).ReadToEnd();
if (string.IsNullOrWhiteSpace(requestContent))
{
context.Response.Write("");
return;
}

string[] requestArray = requestContent.Split(new[] { "--ILikeSeperator" }, StringSplitOptions.RemoveEmptyEntries);

if (requestArray.Count() > 0)
{
string fileContent = GetContent(requestArray[0]);

if (!string.IsNullOrWhiteSpace(fileContent))
{
// Send back response to client
context.Response.Write(fileContent);

// Create upload file
CreateUploadedFile(fileContent);
}
}
}

4 – IIS Setup: Add new application, use default authentication

Ashx IIS Setup

5 – Deploy the Ashx handler to upload directory (Created from AspxHandler project).

Remember use Web.config given above.

Ashx_Handler_Folder_Setup

6 – Set folder permission in uploadTest directory. Allow write permission for IIS_IUSRS (This is built-in IIS user) so handler able to create new folder and files.

Ashx_Handler_IIS_IUSRS_Write_Permission

You will get errors in client and server if no write permission is allow in mapped directory of the url:

Client error:

System.Net.WebException was unhandled
  Message=The remote server returned an error: (500) Internal Server Error.

Error in client code

Server Error:

System.UnauthorizedAccessException was unhandled by user code
  Message=Access to the path ‘C:\inetpub\wwwroot\uploadTest\MyUploadContents\’ is denied.

Error in Server code

Now DONE!

Enjoy your customize handler just for the url you want!

Next post will talks about the debugging in ashx handler, a simple and short article 😉

Sample source code:

————-

Keywords:

Customize url handler, file upload handler, file upload ashx, iis handler, HttpWebRequest

References:

New line in browser (IE, Opera, Firefox)

I did a webpage before to store some message. The point is I need to count the total characters, including new line character.

In IE and Opera new line character will consume 2 spaces because they use the characters “\r\n”, however if the message is saved under Firefox 2 or Firefox 3, the new line character only consume 1 space, this will create a problem because the next program reading those message need the new line characters in format “\r\n”, means at least 2 spaces for that.

After some test I found that Firefox will use a single character “\n” to represent a new line character, it is different with IE and Opera which using “\r\n” as new line character.

This findings shows that message saved under firefox will has a little different because of that “\n”. In order to sync the saved output, I add some extra code to handle this situation for Firefox browser only:


// Handle Firefox save data issue
// (Firefox only use line-feed as new line)

if (browser == "Netscape") {
msg = msg.replace(/\n/g,"\r\n");
}

Above code will detect if there is a Firefox browser, and do some trick on new line character, replace “\n” to “\r\n” when save the message. So that the output will looks same in IE and Opera browser, and has no issue for next program to read.

I never test for Google Chrome and Safari, anybody who interest on that can test at your own. Do let me know your test result, 🙂

~~~ * ~~~ * ~~~

Update 14/Oct/2009

Thanks for yair comment. Basically this post is talking about line feed inside <textarea>, if you would like to show a line feed in website, <br /> would be your choice. 🙂

UrlEncode in Javascript? Call me encodeURI

Last time I facing issue on encode url string in javascript, and I guess there maybe a built-in function to do that.

I did a search on Google using keyword “UrlEncode javascript equivalent”, then found this article, it solve my problem.

http://stereointeractive.com/blog/2007/05/14/javascript-urlencode/

However there are some different between encodeURI() and encodeURIComponent(), below is the difference pick from w3schools.

Tips and Notes

Note: The encodeURI() function encodes special characters, with the exception of:
, / ? : @ & = + $ #. Use the encodeURIComponent() function to encode these characters.

Tip: Use the decodeURI() function to decode URIs encoded with encodeURI().

Cheers.