XML Caching in ASP.NET can be dangerous to your health

Posted by Kyle Heon Fri, 18 Sep 2009 00:03:00 GMT

Today was a day of troubleshooting and fixes. We had a site that was getting ready to go live, hosted on a 64-bit version of Windows Server 2008 (IIS7). I won’t bore you with all the details of all the issues we worked through today but we had one nasty issue that, once it happened it brought the server down; 100% CPU usage by the w3wp.exe process and memory usage steadily climbing. Our error logger was catching mostly one xml argument exception (but with a few variations).

A partial stack trace looked like this:
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.ArgumentException: The node to be removed is not a child of this node.
     at System.Xml.XmlNode.RemoveChild(XmlNode oldChild)
     at System.Xml.XmlNode.RemoveAll()
     at System.Xml.XmlElement.RemoveAll()
This error was at the heart of our navigation framework which makes heavy use of xml and xsl. The process we go through for building a pages navigation looks something like this:
  1. Check to see if the xml navigation file has been cached, if so get it from cache, otherwise load it and cache it.
  2. When navigation is ready to be rendered, it is first manipulated to add in an xml node section that stores the current pages selected states
  3. The modified (in memory) xml is then passed to the desired xsl which handles converting the xml to html and returning the transformed string.

Originally the process of modifying the xml (in memory) looked like this:

protected virtual void AddNavigationSelectedStates()
  {
      /*
      <selected>
          <choice level="1">Selected L1</choice>
          <choice level="2">Selected L2</choice>
          <choice level="3">Selected L3</choice>
      </selected>
      */
  
      XmlNode navigationScheme = this._xml.SelectSingleNode("navigationScheme");
      XmlNode selected = this._xml.CreateNode(XmlNodeType.Element, "selected", "");
      if (null != navigationScheme.SelectSingleNode("selected"))
      {
          selected = navigationScheme.SelectSingleNode("selected");
          selected.RemoveAll();
      }
  
      for (int i = 0; i < base.Selected.Count; i++)
      {
          XmlElement choice = this._xml.CreateElement("choice");
          choice.SetAttribute("level", (i + 1).ToString());
          choice.InnerText = base.Selected[i].ToString();
  
          selected.AppendChild(choice);
      }
      navigationScheme.InsertBefore(selected, this._xml.SelectSingleNode("//navigationScheme/mainNav"));
  }

During stress testing we identified that the problem code was the if (null != navigationScheme.SelectSingleNode(“selected”)) block. As I was the original developer I struggled to remember why such code was there, given that this node should never exist as the page builds. So, after reproducing the errors locally with the above code I removed the if statement and retested. Not a single error. Quickly browsed the site and didn’t notice any issues (I should have looked harder, there were plenty).

We posted an updated build, stress tested the site, still no errors. Then another developer noticed that the site navigation wasn’t working properly. So, back into the source I went. Digging deep I eventually found that each time the XmlNode navigationScheme = this._xml.SelectSingleNode(“navigationScheme”); was run, the section of the document grew with all previous “choices”.

Through more debugging and some pair programming with a fellow developer (and a lot of discussion about what was really happening) we discovered that, while we were never stuffing the modified xml back into cache, it was indeed being updated. I’m still trying to determine why this is but I think I have read somewhere that XmlDocument objects are in memory structures that are passed by reference (and not by value as I originally thought).

Armed with this information we attempted to clone the document and modify that and while that ultimately worked, it didn’t fit into the system we had for navigation render behaviour. With some changes to how we passed along the modified xml we ended up with this modified method (name changed to better reflect it’s newer intent):

public virtual XmlDocument SelectedStatesXml()
  {
      /*
      <selected>
          <choice level="1">Selected L1</choice>
          <choice level="2">Selected L2</choice>
          <choice level="3">Selected L3</choice>
      </selected>
      */
  
      XmlDocument xmlDoc = (XmlDocument)this._xml.CloneNode(true);
      XmlNode navigationScheme = xmlDoc.SelectSingleNode("navigationScheme");
      XmlNode selected = xmlDoc.CreateNode(XmlNodeType.Element, "selected", "");
  
      for (int i = 0; i < base.Selected.Count; i++)
      {
          XmlElement choice = xmlDoc.CreateElement("choice");
          choice.SetAttribute("level", (i + 1).ToString());
          choice.InnerText = base.Selected[i].ToString();
  
          selected.AppendChild(choice);
      }
      navigationScheme.InsertBefore(selected, xmlDoc.SelectSingleNode("//navigationScheme/mainNav"));
      return xmlDoc;
  }

Be sure to note in the code above, the call to this._xml.CloneNode(true); as this is important. We are doing a deep copy of the entire XmlDocument. Manipulation is done strictly to the clone and never the master xml document. So now when we call out to render navigation, it looks like this:

return base.OutputNavigation(
      new XslTransformBehaviour(
          ((XmlNavigation)this.Navigation).SelectedStatesXml(),
          XslHelper.GetTransformer(path),
          ((XmlNavigation)this.Navigation).NavigationArguments
          )
      );

I hope this helps someone someday. I don’t think this behaviour is something I’m going to forget any time soon.

Posted in  | Tags , ,  | 1 comment | no trackbacks

TeamAgile's DataRollback attribute upgraded to VS.2008, .NET 3.5 and NUnit 2.5

Posted by Kyle Heon Fri, 21 Aug 2009 00:26:00 GMT

Nearly two years ago I blogged about an upgraded version of TeamAgile’s DataRollback attribute. Well now I’m doing it again, but this time to say that I’ve upgraded the source for VS.NET 2008, .NET 3.5 and NUnit 2.5.

Refer to the previous blog post for details on how to use this. Grab the binaries or source below:

Posted in  | Tags , , ,  | no comments | no trackbacks

PLINQO

Posted by Kyle Heon Wed, 08 Jul 2009 22:26:00 GMT

About 4 or 5 years ago I used CodeSmith to automate the creation of our data access layers at PixelMEDIA, Inc. which have served us well up until now. Recently we revisited these templates and made dramatic changes to bring our data access layer current with current development trends.

Even still, we are always on the lookout for better ways to generate the standard “CRUD” code. Today I came across PLINQO which really looks to improve many of the short-comings of Linq2Sql. I hope to get a chance to play around with it a bit in the near future.

Posted in  | no comments | no trackbacks

Got my motorcycle license!

Posted by Kyle Heon Fri, 05 Sep 2008 00:20:00 GMT

So I’m a little late in posting this but I passed my motorcycle training road and written test and was in line at the DMV the day after (Monday August 25th) to get my temporary paper NH license with the motorcycle endorsement.

Since then I have pretty much ridden my motorcycle to work every day, in fact I have every day since getting it. I just broke 400 miles yesterday and was hoping to go cruising up to my folks in Maine over the weekend but it looks like we’ll be getting a lot of rain courtesy of those annoying hurricanes down south.

Last weekend I gassed it up for a second time which enabled me to run mileage numbers, turns out I’m getting just below 38mpg which is awesome but I’m looking to be in the high 40’s if not the low 50’s once the engine has been broken in (and as I learn how to control the throttle and shift better).

I’ve already started looking at my replacement ride. This bike was always meant to be a learning bike but I’m already wishing I had more power, at least for the takeoff. I’m currently leaning towards the Yamaha V Star 1300 Tourer in black cherry.

Posted in  | Tags  | no comments | no trackbacks

Learning to ride a motorcycle

Posted by Kyle Heon Sun, 20 Jul 2008 01:23:00 GMT

It’s been quite awhile since I last posted and a lot has happened too. This past May I started getting the itch to buy a motorcycle. I convinced the wife (she was apprehensive, worried I’d get hurt). I quickly registered for New Hampshire’s Basic Rider Course ($110) and then waited (not patiently, I eagerly approached the mailbox every day only to be disappointed, until today).

In June (Father’s Day in fact) I purchased my motorcycle. Over the Memorial Day weekend I went looking at bikes, asked a bunch of questions and sat on a couple small bikes (the Kawasaki Vulcan 500 Ltd and the Yamaha V-Star 650 Custom). I then did a lot of research online and both bikes got many thumbs up for starter bikes. I was all but sold on the Kawasaki except that I wasn’t finding many aftermarket parts for but the Yamaha had slightly better aftermarket support, plus a slightly bigger engine.

I ended up going with the Yamaha for the increased engine size, slightly better aftermarket support, the shaft based drivetrain and the fact that it looked so much more bad-ass then the Kawasaki.

I took delivery a few days later. It was so cool and it had a nice little roar to it (nothing like a Harley, but this is my first bike so it sounds good to me).

Having never ridden I wasn’t sure how to even get the thing moving so I worked to get it into first and takeoff without stalling. That didn’t go so well for me until my dad showed up one Sunday morning and helped me work through it. I continued to practice my starts in the parking lot for another week or more and then on July 3rd went to take my permit test (a 20 question written exam). I passed (just barely—phew) and then that weekend my dad showed up again. He rode the bike over to an industrial area near where we live that has numerous (and empty) parking lots to practice in. After a good 1-2 hours of practice in the parking lot I felt comfortable enough to ride it home (about 2 tenths of a mile).

I continued to practice around our neighborhood, not daring to venture out into the main streets of downtown Portsmouth. It’s pretty crazy where I live so I really had to learn the hard way, right into the fire.

Last weekend my dad came down again and we went out on the open road, taking two trips to where I work (about 5 miles away). I stalled a couple times on the way there but overall did pretty good. This past week my truck has been in the shop so I rode Tuesday through Friday to work (the weather cooperated for me).

As I eluded to earlier, I got my training date(s): August 22nd-24th. This unfortunately falls right when my brothers Jack & Jill has been scheduled (they know, so I’m not spilling the beans). Because this is a non-refundable event I’m still going to go and hopefully I can shoot up to my folks to catch the tail-end of the party.

My permit runs out the end of this month so I have only a couple more weeks to ride, and more importantly only two more Thursdays that I could go in and take my riding exam. While I’m feeling really comfortable on the road and with my bike, I’m not sure I’m prepared for the road test…so I need to decide if I’m just going to wait for training to get my license (assuming I pass) and miss a month of riding time (all of August) OR do I make an attempt and go for my license?

I sadly don’t have any photos of my bike (yet) but I will work to get some shortly and post them to my Flickr Photostream but for now, you can see what my ride looks like here (mine is in black).

Posted in  | Tags  | no comments | no trackbacks

Server 2003 x64, VMWare Server and a 1TB RAID5 NAS array

Posted by Kyle Heon Tue, 20 May 2008 23:56:00 GMT

Early in 2008 I decided to build a new, super beefy system to consolidate my old desktop PC and a small development Fedora Core server. My intention was to go 64-bit from the start so that I could load the system up with 8GB of RAM.

Due to a strange memory issue I was not able to run Windows Server setup with all 8GB of RAM in place, it was weeks before I finally discovered the problem. This system currently has 2×2GB chips in and things work, but if I add in the additional two chips, Server 2003 doesn’t get past the “Starting Windows” screen. Weird.

For the past week or so I have been playing around VMWare Server just to get a feel for how things work. I’ve created virtual appliances running Windows XP Professional, Ubuntu Server, FreeNAS, OpenFiler and also OpenSolaris 2008.05.

From what I have seen so far, VMWare Server is simply one of the coolest technologies I’ve played with in a long time. I can’t believe how simple it is to create new appliances, install the OS into it and start it up.

One of my goals with VMWare Server here is to create a really streamlined WinXP Pro install that I can save a snapshot of but start up slices for my children to play in and install whatever they want. If things go south, I just delete the appliance and start over with the fresh WinXP Pro.

My final goal with this system was to setup a redundant storage solution for my growing library of MP3’s and all my RAW photos. For this I went with a motherboard that had RAID5 onboard and bought 3 500GB 7200RPM Western Digital drives, giving me about 1TB of RAID5 storage.

I want this storage array to be as simple to use as possible and will act as the storage device for all of the appliances running plus the aforementioned music and photos.

Thus the reason I have setup appliances with FreeNAS, OpenFiler and OpenSolaris. None of which has worked out quite like I hoped.
  • It looks like FreeNAS is really designed to run from a USB drive and as such I was not able to really get it working.
  • OpenFiler looks really promising but the interface is very difficult to navigate and while I have figured out how to get “shares” setup through the interface I can’t figure out how to access them from another system.
  • And finally, I looked at OpenSolaris specifically to leverage the incredibly awesome ZFS. The problem is, OpenSolaris is wicked slow, at least when run through VMWare. I’m hoping it’s because I’m doing something so I’ll keep exploring.
  • If all else fails, I guess I’ll format the array with Server 2003 and create shares as needed. I’d imagine that will mean I’ll need to use the FAT32 file system so that non-Windows nodes can access it.

All of this exploration has been a lot of fun. The issues I ran into getting things built and installed was painful but now I know more then I did before.

Posted in  | no comments | no trackbacks

Upgraded to the new Canon Rebel XSi, Old Canon Rebel up for Sale!

Posted by Kyle Heon Sun, 13 Apr 2008 10:44:00 GMT

Since Canon announced the new Rebel XSi I have been seriously considering the upgrade from my now 2-3 year old Rebel XT. The XT has served me quite well and is still an awesome camera, for the price (especially now, as it’s being phased out, you can get it for pretty cheap).

The XSi offered numerous upgrades over the XT and with a recent bonus check from my employer, I felt it was not only in the cards, but worth it.

Earlier this week B&H notified me that they had stock in the new Canon model and so I started watching the local Best Buy. Friday, after work I stopped back in and patiently waited for a sales associate to free up to ask when they would be getting some. He looked it up in his computer and low and behold, they had stock. He was able to track down one—the kit, which is what I wanted (for the upgraded 18-55mm IS lens).

I sadly have not been able to really play around with it but I can say that it is a pretty cool camera and I suspect I’ll be learning all the new features it offers in the coming months. With spring/summer right around the corner, I’m hoping to get some good photos, so watch this space and my flickr space.

So, as the title suggests, my old Rebel XT is up for sale. I haven’t listed it on eBay or anything like that yet, just spreading the word quietly for right now. If you are interested, contact me using the link in the footer. Use a subject line similar to “Interested in your Rebel XT”.

I’m asking $350 for the kit, plus a few other goodies:

I also have an older 28-80mm lens that works perfectly with the Rebel XT which I acquired during my film SLR days. If you are interested in this, let me know as I’m willing to add it to the mix for a small additional amount.

I expect that shipping this bundle will probably run about $15 via UPS Ground, but we can certainly discuss total cost via email if necessary.

Posted in  | Tags ,  | no comments | no trackbacks

TeamAgile's DataRollback attribute upgraded to VS.2005, .NET 2.0 and NUnit 2.2.8

Posted by Kyle Heon Mon, 17 Dec 2007 01:22:00 GMT

I’m currently knee deep with a complete rewrite for one of our large e-commerce sites in .NET 2.0. Part of this rewrite has us finally getting unit tests into the solution.

For the past week I have been working on trying to get a framework in place that allows us to load suitable test data into the testing db for proper unit testing. For this system it is necessary due to all the intricate relationships between products, styles, skus, orders, order line items, etc.

I have been working on a framework similar to what Rails TDD offers, where you specify the fixtures required but continue to run into a strange issue that causes the code to run multiple times for each fixture, even though there is only one test in the fixture.

In an effort to get something in place for this week I began exploring what Team Agile (found via/from Roy Osherove’s ISerializable blog). This has been coined XtUnit.

Even though I met the min requirements of having COM+ 1.5 support (Windows XP SP2 OR Windows 2003) I was not able to get things to work. At first it turned out that I wasn’t sub-classing ExtensibleFixture but then it didn’t like the version of NUnit I had.

As it turns out the source was provided using VS.2003, compiled against NUnit 2.2.1 (2.2.x for sure, believe it was 2.2.1). I’m using NUnit 2.2.8 at this point so I not only upgraded the solution to VS.2005 but also recompiled using NUnit 2.2.8 and so far I think things are working quite well. The DataRollback attribute is working perfectly.

This will work for now in that it at least ensures that tests are atomic, not affecting other tests. It does not however help me ensure that we have appropriate test data in the system. That currently is handled via a nant script that clones the db structure from our dev db into a new local test db and then a data.sql that is run to load initial lookup data.

To make it easier for anyone struggling with the same issues I am providing the upgraded source as well as recompiled binaries for download. You can get them below.

If anyone can explain to me why when adding an attribute at the class level would cause this code to be executed multiple times (with just one test in the test fixture) I would love to hear about it in the comments.

UPDATE: 8/20/2009 – A newer build of this is available here.

Posted in  | Tags , , , ,  | 2 comments | no trackbacks

The Name of the Wind is an impressive debut novel

Posted by Kyle Heon Tue, 04 Sep 2007 23:37:00 GMT

For the past couple of weeks I’ve been engrossed in the massive tome that is titled The Name of the Wind.

It has been quite a long time since I’ve been so heavily invested in a novel, let along a fantasy novel. Between family and work I don’t often have as much time to spend reading as I would like. This book kept me coming back.

Don’t let the fact that this novel is Patrick Rothfuss’ debut novel, it is wonderfully written and keeps you coming back. I found myself stealing 5, 10, or 15 minutes whenever I could continue moving through this 662 page novel.

This is book one in a trilogy which makes waiting till April for book two to hit shelves the most depressing part.

Next up, another debut novel, this one by Scott Lynch titled The Lies of Locke Lamora. Here’s hoping it’s as good as the reviews have said it is…

Posted in  | Tags ,  | no comments | no trackbacks

Little Peter Cottontail

Posted by Kyle Heon Sat, 25 Aug 2007 00:09:00 GMT

The other night after getting home from work the kids came rushing in to tell me to get my camera, that there was a bunny in the back yard. So I grabbed my camera w/my 75-300 lense and headed outside.

Sure enough, there he (not really sure if he really is a he) was sitting in the grass about 20 feet away. This little guy was really tiny, in fact the grass was taller then him when shot from a distance of 10-15 feet while laying on the ground.

Ultimately I had to approach slowly and kneel to get some good shots (due to the height of the grass). I only kept four out of the 131 I took but they all came out really good (I think). You can check them all out here.

This photo below is probably the cutest of them all.

Posted in  | no comments | no trackbacks

Older posts: 1 2 3 ... 11