aspconf is next week. aspconf is a new thing, yet an old thing. Hang around and I'll tell you a bit about it. A few years ago we started c4mvc and there was much rejoicing. The video sharing time we spent was fruitful. People liked it and so did we.
So I ran across an interesting way of marking up Html forms. I thought it was nice, so I decided to bring that into the world of ASP.NET, because there is a (easy to overcome) roadblock in using the method in traditional ASP.NET (it is odd having to distinguish between traditional and MVC...).
I am reading Refactoring: Improving the Design of Existing Code right now. In his discussion on method naming on pp. 110-111 he said something that seemed well said. I thought I would share it.
So today I took my first dive into the new ASP.NET charting component.
A faithful reader of the blog commented on my post the other day about using HttpRuntime vs HttpContext. Anderson's main point is absolutely right, and worth repeating. Here's what he said:
Sometimes I find a discussion on something and I think to myself "you really need to blog this, because you may need to find it again some day and someone else might find it helpful." The adverse side effects of not doing this hit me the other day. I needed this little tidbit, but it took me a while to find it because I didn't blog it the last time I saw it! So here it is.
Now all urls for viewing posts, viewing them by category, and viewing them in the archives, is complete. All courtesy of the VirtualPathProvider...woot!
Seriously, I am going to talk about stuff other than the Virtual Path Provider sometime...:)
So I noticed an oddity yesterday that I just had to track down. I had the path wrong on a css file reference of mine and this was causing an exception to be thrown. Odd, you say? Well, I thought so too. So here is how it actually happened.
When I added some VPP support (locally, not on the web yet) for my blog, I noticed that an unhandled exception was being thrown when I visited certain pages. I had never seen it before; it didn't directly affect user experience at all. I just happened to notice it because I log errors in Global.asax's Application_Error. So I looked at it and I noticed I had the path wrong on a rather inconsequential css file. So I thought to myself, "Why would an invalid css file path be throwing an error." So I followed the stack trace down on the error, and with Reflector, found the answer.
Surprisingly, it was related to the fact that I was now using a VPP. Down in the bowels of ASP.NET there is this StaticFileHandler class. It has a method called "ProcessRequestInternal". This method was called for the request for my css file. If you have a VPP registered, it takes a different path than otherwise. It checks to see if the VPP registered as the first VPP for the hosting environment is the MapPathBasedVirtualPathProvider, and if it isn't, it calls a method called RespondUsingVirtualFile.
Now this VPP thing works like the chain of responsibility pattern. Let's say you register a VPP called "FooVPP". The HostingEnvironment takes it current VPP, the MapPathBasedVirtualPathProvider, assigns it to the "Previous" property of FooVPP and sets FooVPP as its current VPP. If you register another VPP called "BarVPP", that one becomes the current, its previous is set to FooVPP, and its previous is still MapPathBasedVirtualPathProvider. So any request gets handled by BarVPP, and if it can't handle it, it hands it to FooVPP, who handles it if it can. If it can't, in then handles it to the MapPathBasedVirtualPathProvider and it tries to handle it. If it can't, nothing can, and you get a 404.
So, back to StaticFileHandler. It checks HostingEnvironment.UsingMapPathBasedVirtualPathProvider method, which will return false, because it checks to see if the top level VPP is the MapPathBasedVirtualPathProvider. In this case it is not, so it returns false. Because of that it called RespondUsingVirtualFile (in StaticFileHandler).
In RespondUsingVirtualFile it first creates a variable for holding an instance of VirtualFile, and it is of course null. Next it checks the whole chain of VPP's to see if the file exists. Because the path was wrong on the css file, the check comes back false. And therein lies the problem. The VirtualFile instance is only set if a file is found (which of course makes sense). If it doesn't find the file, then it throws a "File does not exist" exception, and then you have the end of this process.
So here's the takeaway lessons on this:
1. Don't have inconsequential css files.
2. Spell your paths right.
3. Be sure to pay attention to exceptions thrown in Application_Error. Don't throw any more exceptions than you need to.
In my last post I discussed the virtual path provider in ASP.NET 2.0 the difference between using url rewriting and using the VPP (Virtual Path Provider model) to handle urls for content that doesn't physically exist in the normal folder structure. I've been thinking more about this and my thoughts are crystalizing, so I thought I would flesh them out in a post.
The more I think about it, I think comparing the two things is like comparing apples and oranges. Url rewriting is for taking a url you get and saying "no, I really want you to go here" under the hood. It's about redirection, though it isn't exactly redirection. The VPP system is about creating an extensible ASP.NET page lookup mechanism that keeps you from having to rely on the file system. If my definitions are basically correct, then using url rewriting for handling virtual pages in ASP.NET 2.0 is like using a wrench for a hammer to knock a nail into some wood (which is what I do when I can't find my hammer); it is using a tool for doing something that works but isn't the most ideal for a job. I don't think there was any other way of doing this in 1.1 because the VPP tool was not available, but now that it is (and given what the two techniques actually do), the VPP is the tool we should be using.
Now url rewriting obviously works for this, and is used for this thing on apache as well. And if someone has a system to do this built around url rewriting, it may not be worth rewriting just because ASP.NET 2.0 gives you a shiny new tool. But going forward, this makes sense. If you want to point a request in a different direction, use url rewriting. If you want to show content that doesn't depend on the physical file system structure, use the VPP.
I ran across something very interesting a couple days ago in ASP.NET 2.0 called the VirtualPathProvider. Essentially, it's some ASP.NET infrastructure that abstracts ASP.NET from using the file system directly, and it allows you to "hook in" to it all and serve pages from something other than the file system.
Because the documentation is a little sparse, and because it looked pretty cool, I dug into it, created a sample, and wrote up a short essay about it. The sample can be downloaded from that page.
I think it has some very interesting possibilities. In particular I'm thinking of using it for the blog to do what most blogging platforms do with url rewriting. Currently the pages are viewed on the site through a generic viewer page with a variable in the query string (which is less cool). This would allow me to do something like /2007/3/15/ThisIsMyBlogPostTitle.aspx.
What I would really like to know is what are the advantages and disadvantages of implementing this with either approach. I see how they're both done, and the the virtual path provider way seems like a cleaner approach. Am I missing something? I know for many, like Community Server, that this would not have been an option when the platform was originally written since this is new in 2.0. But I haven't really heard much of a peep on this thing. Is no one else thinking about it? Are you community server folks thinking about it? Anyway, I would love to hear anyone's thoughts. It seems like a cool technology...
I started reading Programming Microsoft ASP.NET 2.0 Applications: Advanced Topics again recently and ran across something in Dino's book that was piqued my interest. ASP.NET 2.0 comes built with this concept of the Virtual Path Provider.
Here is a little tip of you're playing around with the "Futures December CTP". If you have been using earlier version of the preview code, you might end up putting this in your ScriptManager to load the preview scripts:
3: Name="PreviewScript.js" />
6: Name="Microsoft.Web.Resources.ScriptLibrary.PreviewGlitz.js" />
Bad idea. If you'll do this you'll get either of the following error messages:
1. Assembly 'Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not contain a Web resource with name 'Microsoft.Web.Resources.ScriptLibrary.PreviewGlitz.js'
2. Assembly 'Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not contain a Web resource with name 'Microsoft.Web.Resources.ScriptLibrary.PreviewScript.js'
To fix this, just remove the "Microsoft.Web.Resources.ScriptLibrary." from the "Name" attribute. Was having this problem. Noticed the fix here.
Literal content ('<control:AControl Color="White" />') is not allowed within a 'skin file'.
And then it proceeded to highlight the control declaration in the skin file:
Line 3: <control:AControl Color="White" />
Solution? The control doesn't have a runat="server" attribute. Not the best error message...
Somebody asked how to create a custom server control that does not automatically render a span tag surrounding the contents. Good question. The guy who answered gave two choices, both good.
First, inherit from Control, not WebControl. That's the easiest.
Second, override the render, call the render on all the individual controls, and don't call base.Render().
The first is much easier, unless you already have to do some of your own rendering anyway. If you do, just don't call base.Render().
So, just as an example, here is the difference between rendering inheriting from Control and WebControl, respectively (both have three child controls, a button, a label, and a text box).
<input type="submit" name="myButton" value="Button" id="myButton" /><span id="myLabel">Label</span><input name="myTextBox" type="text" value="TextBox" id="myTextBox" />
<span id="FancyWebControl1"><input type="submit" name="myButton" value="Button" id="myButton" /><span id="myLabel">Label</span><input name="myTextBox" type="text" value="TextBox" id="myTextBox" /></span>
As you can see the differences are all in the outer span, which includes the span tag itself and an id tag for the id given in the aspx page.
Here's the page declaration, for your reference:
<Custom:FancyControl ID="FancyControl1" runat="server"></Custom:FancyControl>
<Custom:FancyWebControl ID="FancyWebControl1" runat="server" />
The first control, which descends from System.Web.UI.Control, only has its child controls rendered, so the id "FancyControl1" never gets rendered into the output.
If you ever create a custom control and try to theme it, you might get the following exception:
The control type 'YourNamespace.YourControlName' cannot be themed.
Add the following attribute to your class: