Archive for June, 2010

Browsing .html/.htm File in IIS Renders a Blank Page in the Browser

June 29, 2010

Scenario

You are running ASP.NET 2.0 and IIS 6.0

You have a .html file in a Virtual Directory in IIS, you open up that Virtual Directory in IIS, right-click on the .html file and click “Browse”. The file comes up in the browser blank. No HTML is rendered. The .html file extension is configured in IIS to use aspnet_isapi.dll.

An hour has passed and you have chewed your arm off at the elbow in frustration and the emergency sacrificial ferrett is looking nervous. Powerful repetitive thuds from your headdesking are waking the neighbours. Your children are crying and saying ‘What’s wrong with Daddy ??”. Molten coils of incandescent rage… (Editor: Enough of that, KThxBi)

Other Symptoms
When you browse the .html file from a remote computer you get “Page cannot be displayed” error message. But aspx files render perfectly. This exponentially magnifies your bowel-twisting madness, screaming fruitbats..(Editor: I SAID ENUFF!!)

What You Need
What you need is a .NET StaticFileHandler in your web.config httpHandler section. i.e.
add path=”*.html” verb=”*” type=”System.Web.StaticFileHandler” /

Here’s the reason direct from the Microsoft Support web site:

Microsoft ASP.NET 2.0 delegates static file processing back to the IIS 6.0 static file handler through the Execute URL server support function. This behavior lets you to run ASP.NET authentication and authorization modules while serving static content.

Because ASP.NET 2.0 delegates static file processing back to IIS 6.0, any explicit script mapping that maps a file name extension to ASP.NET must have a corresponding mapping in ASP.NET. If the corresponding mapping in ASP.NET does not exist, ASP.NET passes the file processing back to IIS. IIS detects this recursion and then sends an empty HTTP response.

Here’s the full article:

You receive a “Page cannot be displayed” error message when you use an ASP.NET application to open an .htm file or another static file that is hosted in IIS 6.0

Now get yourself bandaged up and apologize to the kids. It’s just another day on Earth.

Advertisements

URL Rewriting: Retain URL in Browser Address Bar on Postback

June 16, 2010

The Reason For All Human Existence

We have a HTTPModule which rewrites .html file extensions to .aspx. The aspx file is served but the user sees the URL as .html. This apparently gives us mega Google points which is fundamentally the reason for all human existence and therefore intrinsically justified.

Form Action Attribute: Enemy of Civilisation

The HTTPModule does the URL Rewriting via HTTPContent.Current.RewritePath(realfilename.aspx).
This leaves the the URL that appears in the browser untouched but causes realfilename.aspx to be served to satisfy the Page Request.

BUT RewritePath sets the underlying Form Action Attribute is also set to realfilename.aspx which means that on Postback realfilename.aspx is POSTed to and realfilename.aspx appears in the Browser Address Bar. This drains Google Juice and makes life, work and all existence meaningless. Worse still , the behaviour of the web page was entirely accurate. The page does need to post back to the real page (not the fake one) in order to process the Postback. That happens through the Form Action Attribute: that’s what its for.

False and True Friends

The #1 recommended solution to this problem on teh Greater Google is to remove the Form Action Attribute entirely from the page by implementing a custom HTML Form Control and overriding the Render method. Once this is done, the Form apparently posts back to the URL in the Address Bar. But I didn’t want to mangle my page that way as it leads to downstream problems and besides, I really did need to postback to realfilename.aspx.

Examining one of our existing Web Pages that handled this scenario correctly, I noticed the form was wrapped in an AJAX UpdatePanel. Yeah, that made sense, the full postback would be suppressed maybe changing some behaviours, so I did the same thing – but no bananas – still the postback put realfilename.aspx in the Browser Address Bar.

I then unleashed Firefox’s glorious FIREBUG to have a closer look at the requests generated on the existing good website and the new bad website. The Net Panel showed me that a POST operation was appended to the list of Requests for the page, while on the bad website a brand new GET was invoked, in Firebug’s Net Panel the GET would clear all the entries and repopulate it with entries with the fresh Request. Suck.

An even closer look at the existing website showed me that not only was the whole HTML Form wrapped in an UpdatePanel but that the Web Page was actually a Content Page belonging to a Master Page, not a Web Page in its own right. Would that really make a difference ? YES!

Live Worth Living Again

To suppress the full .NET Postback with an AJAX Postback I had to refactor the Web Page so that it was a Content Page and (of course) link it to a Master Page and wrap the whole of the Content in an UpdatePanel. Like so:

asp:Content ID=”Content1″ ContentPlaceHolderID=”ContentPlaceHolder1″ runat=”server”
!– Whole page content is wrapped in an UpdatePanel.
This means all postbacks will be ajax postbacks which means that html extension will
be retained on postback which is what we need for URL Rewriting.
If we permitted a full postback, the postback would be posted to index.aspx and the address bar would
be updated with the aspx URL thus overwriting the pretty html extension. All this occurs because
the form action attribute is set to index.aspx (the real page) even though the URL has been rewritten
to index.html (the pretty URL)–
asp:UpdatePanel runat=”server” ID=”upIndex”
ContentTemplate
…oodles of Content here…
/ContentTemplate

The corresponding Master Page is but a shell and looks basically like this:
body
form id=”form1″ runat=”server”
asp:ScriptManager runat=”server” /
div
asp:contentplaceholder id=”ContentPlaceHolder1″ runat=”server”
/div
/form
/body

I don’t really know why moving all the content to a Content Page should be required to suppress the full postback. But it works for me.