Category Archives: C#

Remove ViewState From ASP.NET Page to Improve Performance

In a previous post, I eluded to the fact that I remove the ViewState from our ASP.NET pages to improve performance. I can’t take credit for coming up with the idea though. Originally, I got the idea and solution I wanted to implement by reading this article at EggHead Cafe. The solution I chose was to store the ViewState on the web server’s file system and reference the file in the page sent back to the client. I’ll outline how I did that below.

The first thing you’ll want to do is create a new Page base class that inherits from System.Web.UI.Page so you can override some of its methods, namely SavePageStateToPersistenceMedium and LoadPageStateFromPersistenceMedium. This will allow you to save the page’s ViewState to the file system and then re-load it on a post back. Let’s start with saving the ViewState to the file system.

protected override void protectedSavePageStateToPersistenceMedium(object viewState)
{
	// Serialize the view state into a base-64 encoded string
        LosFormatter los = new LosFormatter();
	StringWriter writer = new StringWriter();
	los.Serialize(writer, viewState);

	string guid = NewGuid();
	string vsp = ViewStateFilePath(guid);

	// Save the string to disk
	StreamWriter sw = File.CreateText(vsp);
	sw.Write(writer.ToString());
	sw.Close();

	// Save the guid in a form field
	ClientScript.RegisterHiddenField("__VIEWSTATE_GUID", guid);
}

So, let’s step through what we’re doing here. The first few lines of code, we’re serializing the view state. Next, where we call

string uid = NewGuid();

We’re creating a new guid that we will use in creating the file name on the server for the actual value of the current view state. NewGuid() just returns a new guid value from the System.Guid class.

Next, we need to create a path to where we’re going to store the file as well as its file name. Now, you can do this any way you want as long as all of your files end up being unique. You can’t go overwriting one guy’s view state with someone else’s. Now I based mine on basically the guid appended with the current request path minus the extension and replacing the slashes with dashes. So, my filename looks like:

string fileName = guid + "-" + Path.GetFileNameWithoutExtension(Request.Path).Replace(
    "/", "-") + ".vs";

Where the guid was passed in to the function that I called to create the view state file path.

So now that we have a path to where we can write the file, we can go ahead and do so using the StreamWriter that we created. Now, the last thing to do is spit out where we can find the view state to the client. This is done by registering a hidden field with the client:

ClientScript.RegisterHiddenField("__VIEWSTATE_GUID", guid);

That GUID allows you to recall the proper file for the client when you need to access the ViewState.

So now you’ve persisted the view state to the file system. Now all that’s left is to load it up when needed, which is done with LoadPageStateFromPersistenceMedium(), which is below.

protected override object LoadPageStateFromPersistenceMedium()
{
	string guid = Request.Form["__VIEWSTATE_GUID"];
	if (guid == "")
		return null;
		// determine the file to access
	if (!File.Exists(ViewStateFilePath(guid)))
	{
		return null;
	}
	else
	{
		// open the file
		StreamReader sr = File.OpenText(ViewStateFilePath(guid));
		string viewStateString = sr.ReadToEnd();
		sr.Close();
		// deserialize the string
		LosFormatter los = new LosFormatter();
		return los.Deserialize(viewStateString);
	}
}

This approach gives you the ability to minimize the amount of data that you have to send over the wire to a client browser. There are other solutions to this like storing the ViewState in memory, but I felt that it was a waste of resources if a ViewState might only be used once and then abandoned. The one thing you’ll want to do is manage your saved ViewState files on your disk. These files can get out of control, especially when you get a lot of visitor’s. So what I did was just set up a Scheduled Task in Windows to clean up stored ViewState’s every three hours. This works out pretty good since a ViewState really won’t be needed beyond that timeframe.

Anyway, I hope this solution helps some other C# ASP.NET developers out there. It sure worked out great for me!

Nextopia Search Integration

We’re on our third search integration in the last few years. We used to use SLI Systems for search. They have a phenomenal service for search, but its a little more expensive than our small company can afford. So, last year, we decided to switch to the Google Mini. We had heard some good feedback from some other sites that had implemented it and decided to go for it. The cost for us was only $3,000 for the Google Mini device, the $200 a month co-location fee we pay, and some development time.

In the end, the Google Mini just didn’t give us consistent results for the how we were using search. We were able to implement a pretty cool solution that let you refine results by price and category, something I hadn’t seen anywhere else. But at the end of the day, not being able to get a result for something as simple as an item number was just too frustrating. I tried a lot of different techniques with the Mini to get the results to come back properly, but at the end of the day, it just didn’t cut it. I’m not sure if its because of the fact that it depended on spidering the site or not that gave us issues, but we had to start looking at other solutions.

My boss sent me an article about three different search solutions and compared them for readers. After reading, we decided to give Nextopia a shot. SLI was one of the other choices, and as much as I liked their service, we just still couldn’t afford it. The reasoning for trying Nextopia was that it provided similar features that SLI had and the price was way more appealing. You can get search for as little $995 a year. We’re paying a bit more than that for our three sites that get decent traffic, but its still affordable for our small company.

Nextopia provides you with a search page and template, but it didn’t fit in with the look and feel of our site. Since I wasn’t happy with the code they wrote for it either, it was more work to modify their version than to roll my own. Luckily, the code we had for our SLI and Google Mini implementations was written well enough that I was able to abstract that code even more (had to refactor a bunch of it) and roll a Nextopia version of our pre-existing search pages. What’s nice is now we have a C# library with 3 search integrations and the ability to roll new ones at any time we want.

The integration process took about a days worth of development and testing, which isn’t bad for integrating a 3rd party search solution. Granted, the refactoring of our search library took more time, but the actual Nextopia integration took a day. We’re really happy with the results it can provide and how quickly it can provide them. This definitely gives our users the robust search solution they need to find out products reliably and quickly. I’d say the only downside to the integration though is I can’t automatically send them a feed of our products. I have to update it manually on a regular basis, which is kind of annoying but not the end of the world. Anyway, if you’re looking for an e-commerce search solution, I highly recommend Nextopia.

ASP.Net HyperLink Control And Html Encoded Ampersand’s

I just ran into some odd behavior with the HyperLink control ASP.Net. Per the W3C, you’re supposed to HtmlEncode ampersands, using & instead of ‘&’ when building URLs in your HTML code. The reason is that the ‘&’ is assumed to be an entity reference. What’s nice is most web browsers can recover from this type of error, but if you want your site to pass validation, you need to use & instead.

So I hooked up all of our URLs to use this method, especially when we wrote out URLs in our C# classes. What I found odd was if I did this using a HyperLink control instead of an HtmlAnchor control, .NET would write the & out in the URL instead of using ‘&’. Naturally this broke our site as query string references weren’t parsed properly. The fix was to use an HtmlAnchor instead.

I’m not really sure why .NET does this or if there’s another workaround for it, but this solution worked for me. I’d be curious to know the reason behind the behavior though.

Import Costumes Goes Live!

Our new e-commerce site, ImportCostumes.com, has gone live!  Its been months since development began and after lots of blood, sweat, and tears (mostly over PayPal account setup and integration; more on that to come later), we’re ready to take orders.  We have lots of cool men’s costumes and women’s costumes.  We also have a large selection of boy’s and girl’s costumes, and not to mention awesome accessories!  Come check it out and buy some stuff!

Weird IE6/ASP.NET SSL Bug

We found a weird IE6 bug in Fright Catalog and YumDrop today.  Turns out, when in the checkout process, IE6 would display a message to the user that they were navigating from a secure page to an insecure page.  Firefox, IE7, and Camino wouldn’t display any notification message at all.  The IE6 warning was totally bogus, since the resulting page was definitely secure (little gold lock, no messages, etc.).  For a while, I thought it was a bug in IE6, but the more I thought about it, that didn’t make much sense. 

That’s when I discovered that the notification only came up on a PostBack on a checkout page, not when the page first loaded.  So, knowing that we manage our secure pages using what we call a Redirect Manager, I took a look at that.  After some digging, I realized I was kind of barking up the wrong tree, and the real issue was the lack of a trailing slash on the URL.  This is something that we can either fix in our redirect or in the Secure Redirect module we use.  What I found really interesting though, is that this wasn’t an issue in Firefox, Camino, or IE7.

New FrightCatalog.com – 2007

Its been quite a long week. Late last night saw the coming of the latest edition of FrightCatalog.com. I think you’ll notice the more product centric slant its taken on this year. A little less glitz, a little more practicality. It should be MUCH faster too. Same framework as YumDrop.com and the soon to come ImportCostumes.com. Thanks for Kyle’s help, even though he’s moved on to a new venture.

The Debugger IS Your Friend!

I’ve been trying to contribute (when I have time) to the ASP.NET Forums lately. I’ve noticed that a lot of people who are new to ASP.NET don’t seem to know to use the Visual Studio debugger. When you see funky things going on in your code or behavior that you can’t explain, jump into the debugger. It’s saved me major headaches before. That and its good to walk through your code line by line for testing purposes. It makes you analyze each line if cide to make sure its doing what you expect it to do. So, moral of the story, don’t be afraid of your debugger, it’s your friend!

Norton AntiVirus & ASP.NET Request.UrlReferrer

I like it when my code works. Most developers do. What I don’t like is when code I KNOW works all of a sudden STOPS working. I spent a good 3 hours ripping my hair out trying to figure out why all of a sudden UrlReferrer was always null in my ASP.NET application. A week ago, my code worked great. Today it doesn’t. I did a lot of digging, asked a couple questions on the ASP.NET forum, but no luck. Then today, I stumbled upon this thread. Could this be? A third part application, one I use to protect my development machine, be hosing my app? Turns out it was. Calling the same code from my MacBook worked as expected.

So what happened? I think a NAV virus definition update changed how the headers appear in HTTP requests from my machine, as stated in the article. I realize we depend on these third party virus protection software applications to protect us from malicious software and the like, but this is crazy. At least tell me you’re doing it and then give me an EASY way to turn it off.

Another interesting implication of this, that was briefly touched on in the above mentioned thread is, would this affect statistics capturing software? Would the stats in Google Analytics be skewed? My guess is yeah, to some degree they will be if header information is held back. What are other people’s thoughts on this?

ASP.NET Caching

There are a few types of caching in ASP.NET, specifically Page Output Caching and Object Data Caching. There are whole hosts of articles out there on using the cache, but for the purposes of this post, I’m going to talk about just using Object Data Caching. To many, this will be obvious, but some cache code I wrote recently made me remember that this can sometimes be confusing in the context of an ASP.NET page.

Typically, you can access the cache from just calling Cache.Add or HttpContext.Curent.Cache.Add. This gives you access to the application wide Cache object. Any object you cache here will be available to any class within your application for the time period you specified for the cached object.

But what if you want to just cache an object for a request? Say you have an item object that you reference on 4 or 5 controls on a page? You don’t want to go to the DB to get the data each time you reference it. Instead, use the HttpContext.Current.Items collection and put your object there. It will be good for the duration of the request.

The two are very different. The first will make your cached data available application wide, to all requests. This can be dangerous if the data might be different for one user than it is for another. The second is available only to the current request. Use this if you load up an object say from the database in one control, but need it in subsequent controls that make up the same request.

Be careful with your cached objects and keep an eye on where you’re putting them. Not doing so can have some potentially disasterous effects.