Don't you hate it when you can't find an answer to your problems after searching Google? I know I do. I've been trying to get the Front Controller pattern (implementation) working, but seem to be having a lot of issues. Hopefully, others will run across this post instead of wading through the hundreds of dead-end forum posts and walk-throughs. I'm sure there is one place that answers all my questions, but as of now, I'm left to the wonderful world of Google.
Anyway, while working on this solution, I ran into several problems. All of which seem to be common. Hopefully, I can try to knock them out one-by-one...
Configuration Sections
This wasn't as big of a deal as the rest of the areas, but I wanted to touch on it to help ease some pain for anyone else going through these hassles.
The pattern implementation suggested adding a controller.mapping section to the Web.config file. I would advise against this approach. While I do not see anything fundamentally wrong with it, it caused me a bit of headache when I first attempted it - this might have been because I was trying a few different things with it. For the sake of simplicity, what I did was reused what was built into ASP.NET: System.Configuration.NameValueSectionHandler.
Here's the config and mapping sections that I chose to use. Feel free to change the names as needed, but remember what you change them to - you will need to reference them in code.
<configSections>
<sectionGroup name="controllerSettings">
<section
name="urlMappings"
type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</configSections>
<controllerSettings>
<urlMappings>
<add
key="/Virtual/FakePage.aspx"
value="~/RealPage.aspx" />
</urlMappings>
</controllerSettings>
The reason I changed some of the names is because I'm hoping to expand the controller capabilities later. The most important thing to note here is that the type attribute of the <section> element must have the version, culture, and public key token in order to work. At first, I abided by the guidance and attempted to use my own section handler, but to no avail. I'm sure it isn't hard to get this to work, but right now I'm just interested in a proof of concept and basis for future work; hence, reusing built-in classes.
Oh, and, in case you're wondering, I'm using .NET v1.1. Check your machine.config (C:\WINNT\Microsoft.NET\Framework\v###\CONFIG) to see what appropriate values might be for your system.
HTTP Handlers
HTTP handlers respond to ALL requests within the ASP.NET environment. The pattern implementation specifically covers .aspx extensions, and I will stick with that, for now. First off, when I say that the handler responds to all requests, I am including the Server.Transfer() redirects, as well. This is important to remember later.
When setting up the handler within the Web.config file, remember that the wildcard path that you use cannot apply to the true path to the file. For instance, the following does not work...
<system.web>
<httpHandlers>
<add
verb="*"
path="*.aspx"
type="Indigo.Web.HttpHandler,Indigo.Web" />
</httpHandlers>
</system.web>
The problem is that when the fake page is transferred to the real page, the real page also abides by this path. So, what you should use is something that is specific to your fake page names (like “Fake*.aspx“). If you don't, you will end up getting a blank page or an error message (see next section).
I'm sure that there are a few better ways to accomplish this; but, I just want it to work for right now. If anyone knows of better ways to do it, please let me know.
Server.Transfer() or Context.RewritePath()
I've seen a lot of discussion about Context.RewritePath(), but most of this is implemented within the Application_BeginRequest() method, which does not seem like a sound practice to me. I may be wrong, but I would need to look into it more to understand it better. As for now, tweeking the Web.config seemed to get my Server.Transfer() to work - I was getting the following error (where “FakePage” is the requested page):
Error executing child request for FakePage.aspx
I was looking all over for an answer to this error, but to no avail. I can't remember where I ran across the HTTP handler idea, but that seemed to fix the problem.
Right now, I'm wondering which solution is better: Server.Transfer() or Context.RewritePath(). The rewrite seems to be a little odd as far as how it works, but I didn't care enough to dig into it more than to see what it was. After getting the transfer to work, I pretty much just put everything down. If anyone knows of any pros/cons for using one or the other, please let me know.
Passing QueryStrings to the Real Page
After setting things up, I wanted to send the FakePage.aspx to RealPage.aspx?Show=Section1. The problem seems to be that I can't read the QueryString on the real page. I placed the entire URL in the Web.config file, but for some reason that didn't work. It's almost as if the transfer ignores it. If I use the QueryString in the fake page, then everything works fine.
I'm still working on this, but am not sure when I'll get a chance to finish things up. I'm trying to avoid custom code to fix the QueryString problem. I'd like to have configuration information be good enough, if possible. I'm sure I'll figure something out.
Please let me know if you find any issues of your own when attempting to implement this pattern (or any others). Hopefully, I can attack those in round 2, when I finish things up - that will probably be next weekend. We'll see.