Congratulations, Boston
Congratulations to the Boston RedSox who have finally broken the “curse of the Bambino“. While Im not a RedSox fan (go Dodger Blue), I gotta say that starting in the ninth inning of game 4 of the ALCS , they were completely dominating.
They have been bringing their A game every single night and it shows. To come back from 0-3 to beat the Yankees, and then sweep the St Louis Cardinals is incredibly impressive. They so dominated the Cardinals that the Cardinals never even had a lead at any point in the World Series… Stunning…
The toughness and determination shown by the RedSox team is something for the ages. Curt Schilling could hardly walk for game 6 of the ALCS (due to a ruptured tendon in his ankle) and was out on the mound bleeding through his sock to pitch the ball for his team. For game 2 of the World Series, he had deep tissue stitches. The morning of game 2, he could not walk because of a damaged nerve. Doctors were able to get him stitched up in time to throw the ball that night. Keep in mind that they stitched things in the *wrong* place, intentionally. Once he was done, he went in and had the stitches removed, only to have to look forward to off-season surgery. Schilling’s performance in this postseason is easily the grittiest performance I have seen in sport. Ever.
As I close this post, I do hope that Boston fans remember their sanity tonight in their celebrations. Please be safe…
ASP.NET pluggable module implementation
For an ASP.NET project that I’ve been working on for quite a while, we wanted to have a pluggable module type of page architecture. We would have one main page (default.aspx) which would have a panel control which could get different controls loaded into it.
The way that we originally implemented this was to have a base control that all of our ASCX files would derive from. As detailed in a previous post, creating base classes is something I always do when creating a new project.
public class ControlBase : Control { public SessionManager SessionManager { return SessionManager.Instance; } }
Now, in our original implementation, we added all the modules to the web.config file.
<modules> <add key="myModule" value="~/path/to/myModule.ascx" /> </modules>
Modules were then loaded in the main page class like this:
protected override void OnInit(EventArgs e) { base.OnInit(); Hashtable modules = ConfigurationSettings.GetConfig("modules"); ControlBase ctl = Page.LoadControl((string)modules[Request.QueryString["module"]]); myContainerPanel.Controls.Add(ctl); }
The more I worked with this and added new controls into our framework, the more disgruntled I became with it. It always seemed like there was more to adding a new control that really should be there. I also had tied a dependency to using ASCX files for my controls, which I didnt really care for either. There are some wierd cases where you may want to have code completely render a control.
Because of this, I started to think about ways that I could improve this idea. Design patterns to the rescue…
The idea would be that a class would be responsible for creating the control, rather than the OnInit method of the page. This led to the realization that I would have some common interface to key and create a control.
public interface IControlFactory { string Name { get; } ControlBase CreateControl(); }
Now, my derived controls have a code structure that looks something like this:
public class MyControl : ControlBase { class Factory : IControlFactory { public Name { get { return "MyControl"; } } public ControlBase CreateControl() { Page page = (Page)HttpContext.Current.Handler; return (ControlBase)page.LoadControl("~/path/to/myControl.ascx"); // note that this works with ascx files, but we could just as easily // do return new MyControl(); if our control is completely rendered with code. } } // rest of MyControl class goes here }
The missing component now is a class that tracks these IControlFactory implementations and returns the appropriate instance based on a passed in key. Introducing the WebControlFactory class…
class WebControlFactory { private static Hashtable factories; private WebControlFactory() { } public static void Register() { factories = new Hashtable(); foreach(string file in Directory.GetFiles(HttpContext.Current.Server.MapPath("~/bin"), "*.dll")) { try { FileInfo fileInfo = new FileInfo(file); string assemblyPath = fileInfo.Name.Replace(fileInfo.Extension, ""); Assembly asm = AppDomain.CurrentDomain.Load(assemblyPath); foreach(Type t in asm.GetTypes()) { if(!t.IsInterface && !t.IsAbstract && typeof(IControlFactory).IsAssignableFrom(t)) { try { IControlFactory controlFactory = (IControlFactory)Activator.CreateInstance(t); factories.Add(controlFactory.Name, controlFactory); } catch (Exception e) { Trace.WriteLine("Exception encountered loading type '" + t.FullName + "': " + e.ToString()); // this is deliberately ignored, as any error in loading the type should just involve // continuing on } } } } catch (Exception e) { Trace.WriteLine("Exception encountered loading control: " + e.ToString()); // this is deliberately ignored, as any error in loading the assembly should just involve // continuing on } } } public static ControlBase CreateWebControl(string name) { if (factories.ContainsKey(name)) { IControlFactory factory = (IControlFactory)factories[name]; return factory.CreateControl(); } throw new InvalidOperationException("No factory registered to handle '" + name + "' controls."); } }
Now, the final steps to implement this new method would be to add a call to WebControlFactory.Register() to the Application_Start method in Global.asax. The register method is responsible for scanning any assemblies in the bin folder, scanning their types for IControlFactory implementations, and adding them to a hashtable if they do.
The second thing to do here is to modify our OnInit method to take advantage of this new class:
protected override void OnInit(EventArgs e) { base.OnInit(); ControlBase ctl = WebControlFactory.CreateWebControl(Request.QueryString["module"]); myContainerPanel.Controls.Add(ctl); }
This has solved my problems with the original implementation. I no longer am limited to ascx files for controls, and I also dont have to jump through the hoops of adding new modules to the web.config file. Using this object model, I am able to create web controls in a separate assembly, drop them in the bin folder and go.
I understand that this technique will be obsoleted by VS.NET 2005 and master pages, but for now, I think this is an elegant technique and I hope you find some value from it…
Edit and Continue in C# 2.0
I’m sure that by now everyone has heard that Edit and Continue will be a part of Visual C# 2005. It’s taken me a while to get my thoughts in order regarding this major announcement.
First off, let me say that I’m really pleased that Microsoft is listening to its user base and implementing features that they are asking for.
Given that, I want to go on record as saying that Edit and Continue is one of the worst things to happen to programming. Ever.
In my experience, I’ve noticed when handling a bug, the first thing that most people do is load up the project, hit F5, and off they go. Why not execute the program, find where the bug occurs, take a look at the error message and *think*. Think about what might be causing the issue. This can be a lot quicker than single stepping through 200 lines of code.
Now, I’ve heard the arguments from people that say that edit and continue is a godsend for those quick typos, incorrect connection strings, etc. The way I look at it, users have been asking for three things from Whidbey (in no particular order): refactoring, edit and continue, and unit testing. I believe that E&C would be unnecessary if more effort was placed on the other two items. You dont need to modify running code, if you have a effective unit tests. The unit tests should have caught these typos. The tests that fail should be so isolated that there is no question of where the error is occuring. This means that you can go to the source of the problem, and fix it… without ever running your program in debug mode.
Lastly, another drawback to E&C is that it can be quickly used to fix something. However, I personally believe that it also leads to band-aid programming. Patching something quickly to make it work, rather than looking at the root cause of the problem. This is bad, and just leads to more issues down the road.
Edit and continue is just a quick way to hack and bang on something to make it work, without investigating the root cause of the problem, and I personally wish that MS would give refactoring and unit testing the time that is now being taken up by edit and continue.
Of course, thats just my opinion. I could be wrong…
Steve Ambron
I got a note today from a very good friend of mine. Steve and I have known each other for almost 14 years now. Several years back, Steve joined the Army and last November, he got called on by our country to serve in Iraq. He spent almost a year over there in the desert in conditions I cant even begin to imagine.
His note today let me know that he was home at last, decompressing and spending time with his wife.
I’ve repeatedly expressed my gratitude to Steve for doing what he does. We have the freedoms that we do because people like Steve stand up to protect our country. Regardless of your politics, I think everyone should thank a soldier for the sacrifices made on our behalf.
Thank you, Steve. You’re my hero.
VM Goodness
Virtual PC 2004 Service Pack 1 is finally available for download. Also available today from MSDN subscriber downloads is Virtual Server 2005.
Hopefully, this resolves my problems with XP SP2 on my VPC images. I’m also looking forward to working with Virtual Server 2005 and the Yukon betas.
Enjoy!
Goodbye, Superman
By now, most of you have heard that Christopher Reeve passed away yesterday at the age of 52. There is something to say about Reeve’s optimism and steely determination to walk again after his tragedy. This was a story that should have ended differently.
Rest in peace, Superman…
ASP.NET Security Vulnerability
A lot of discussion has been going on in the blogsphere over the last few days regarding a severe security vulnerability in ASP.NET. This vulnerability is present in all versions of IIS.
What You Should Know About a Reported Vulnerability in Microsoft ASP.NET
This page was updated October 7, 2004, to include information about a newly released mitigation option, an HTTP module installer. This module protects all ASP.NET applications on a Web server against canonicalization problems that are currently known to Microsoft as of the publication date. We will continue to update this page as additional guidance and resources become available.
Microsoft has also released an ASP.NET ValidatePath Module that web administrators can apply to their web server. This will protect all ASP.NET applications against all canonicalization problems known to Microsoft.
Make sure you get your systems patched, people…
DateTime and Quarters
This has been driving me absolutely up the wall. I’m trying to calculate the fiscal year quarter for a specific date…
I can get the calendar quarter using this formula…
quarter = (month + 2) / 3
Quarter 1 : 07.01 – 09.30
Quarter 2 : 10.01 – 12.31
Quarter 3 : 01.01 – 03.31
Quarter 4 : 04.01 – 06.30
Your mission, should you choose to accept it, is to write a formula that gets the correct quarter based on the table above. I want a pure formula, no if/else conditions…
*The prize:* I’ve got a GMail invite for the first one to post a working formula for this problem. Make sure that you leave an email address so that I can send you the GMail invite. Your email address is never shared, nor published on the website.
A hint: (((calendarQuarter + 2) % 4) + 1) works if the FY starts in April.
*Update:* A coworker emailed me privately with the solution to this problem.
public static void Main(string[] args) { for (int month = 1; month <= 12; month++) { Console.WriteLine("Month {0} is in fiscal quarter {1}", month, GetQuarter(month)); } } private static int GetQuarter(int month) { int calendarQuarter = (month + 2) / 3; float f = 2.5f - (float)calendarQuarter; return calendarQuarter + ((int)(f / Math.Abs(f)) * 2); }
Thanks, Eric…


