Speaking at DevReach in Bulgaria

Thursday, August 28 2008         No Comments

125x125-devrach I'm very excited to be speaking at the DevReach conference in Bulgaria in October.  It will be my first international conference speaking experience (though I spoke to a user group in Moscow last year - my first international talk).  I'm told this show is great, with a lot of good content and a lot of fun.  I know most of the speakers, and I have to say that (with the possible exception of me) it's a very impressive lineup.  I'm really looking forward to it, and I hope to meet a lot of new people and put faces to names with some of the folks in Eastern Europe with whom I've corresponded only by email.

I'll be giving a 2-part talk on Pragmatic ASP.NET Tips, Tricks and Tools.  This is an updated version of a talk I gave at DevConnections last spring, which unfortunately just had too much material to fit the time available.  I'd already trimmed a bunch of content from that talk, so what I've done this time around is split the presentation into two parts, the first being code tips and tricks, and the second focusing exclusively on (mostly free) tools.  I'm always interested in learning about new tools and adding them to my talks, so if you have a favorite developer goodie you've recently discovered, please share it in the comments.

The DevReach conference will be held in Sofia, Bulgaria at the International Exhibition Center, on 13-14 October, 2008.

Render Control as String

Thursday, August 28 2008         No Comments

When working with AJAX and Web Services it's often nice to be able to render ASP.NET controls as strings, so the rendered HTML can be sent back to the client to replace the contents of a <div> or something like that.  The standard way of achieving this is to use the RenderControl() method, exposed by all ASP.NET controls.  Unfortunately, the RenderControl() method doesn't simply return a string - that would be too easy.  Instead, it takes in an HtmlTextWriter which it will render the control into.  No problem, just new one of those up and... not so fast.  You can't actually create an instance of an HtmlTextWriter without first having a TextWriter.  And since you really want a string when this is all said and done, a StringBuilder would be nice to have as well.  So, a few using() statements later, you end up with something like this as the basic pattern:

StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
    using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
    {
        myControl.RenderControl(textWriter);
    }
}
return sb.ToString();

You can take this technique and apply it to a real control in a web method like this example, that renders a Panel with two Label controls in it.

[WebMethod]
public string GetPanel()
{
    Panel myPanel = new Panel();
    Label myLabel1 = new Label();
    myLabel1.Text = "First Label";
    Label myLabel2 = new Label();
    myLabel2.Text = "Second Label";
    myPanel.Controls.Add(myLabel1);
    myPanel.Controls.Add(myLabel2);
 
    StringBuilder sb = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
        using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
        {
            myPanel.RenderControl(textWriter);
        }
    }
    return sb.ToString();
}

I have another blog post on how to render a user control as a string if that is what you really want to do.

The thing to notice about this code for rendering an ASP.NET control as a string is that it's rather repetitive and verbose.  However, it also is the same for any System.Web.UI.Control, and so it is an excellent candidate for an extension method.  Add something like this to a namespace that is referenced in your code to create the extension method:

public static class ControlExtenders
{
    public static string RenderControl(this Control control)
    {
        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
            {
                control.RenderControl(textWriter);
            }
        }
        return sb.ToString();
    }
}

Now the code to render a control becomes simply myControl.RenderControl();.  Our GetPanel() web method can be rewritten to use the extension method like so:

[WebMethod]
public string GetPanel()
{
    Panel myPanel = new Panel();
    Label myLabel1 = new Label();
    myLabel1.Text = "First Label";
    Label myLabel2 = new Label();
    myLabel2.Text = "Second Label";
    myPanel.Controls.Add(myLabel1);
    myPanel.Controls.Add(myLabel2);
 
    return myPanel.RenderControl(); // extension method
}

I discussed this approach briefly on a recent interview on Craig Shoemaker's Polymorphic Podcast.  You can listen to the show here.

Subscribe to Steve's Blog

Testing Legacy Code

Wednesday, August 27 2008         No Comments

P10854253 Oren wrote today about a fun problem he'd run into with trying to TDD some changes to some code about which many of his assumptions were proving incorrect.  The problem is that each test he wrote that verified one of his assumptions needed to later be fixed when he found the underlying assumption wasn't true.  The result was a lot of thrashing and not a lot of productivity.  The solution in this case for him was to worry first about just verifying that the code does what it does

This caught my eye because yesterday I was talking about this very thing with Brendan and the name used by Feathers in Working Effectively with Legacy Code (my review) eluded me.  And of course, that's been bugging me ever since but I lent my copy to another developer.  So Oren's post finally forced me to look it up - the Software Vise.

Software Vise

When we have tests that detect change, it is like having a vise around our code.  The behavior of the code is fixed in place.  When we make changes, we can know that we are changing only one piece of behavior at a time.  In short, we're in control of our work.

In short, when you have no tests and you're working with legacy code that you don't fully understand, a good place to start is to write tests that simply confirm that whatever the code does, it keeps on doing.

Recent Podcasts

Tuesday, August 19 2008         No Comments

My recent DotNetRocks interview with Carl Franklin and Mark Dunn is live now.  The three of us discuss our experiences as small business owners.  I also did a show with Craig over at Polymorphic Podcast last week that should be live next week on caching and performance with ASP.NET.  I did a similar caching show last year on dnrTV that runs through some nice demos and has sample code with it, but the show with Craig for PP adds a few more things (though without the screencast and demo code - audio only).  I appreciate all feedback and hope you enjoy the shows!

DotNetRocks Talk on Business and Entrepreneurship

Monday, August 11 2008         No Comments

A couple of weeks ago I did a DotNetRocks show with Carl Franklin and Mark Dunn in which we discussed our collective experiences with running our own businesses.  We had a good time and shared some of our lessons learned.  In some ways it was similar to the discussions Julie Lerman and I have proctored a couple of times as Birds of a Feather talks at TechEd shows.  Toward the end of the show, I recommended a book that I think any would-be entrepreneur should read, which is:

This book does a great job of explaining the difference between being really good at and passionate about a particular craft or skill (e.g. writing software) and running a business centered around performing that task (e.g. running a software or consulting company).  As I write this, I'm thinking it's probably about time I re-read this book, as I'm quite certain I haven't fully grasped all of its lessons.  Key takeaway: if you're excited about the former but not the latter, think hard (or find a partner) before going into business for yourself.

The DNR show is set to air on August 14th, so look for it then.

Client Cache Headers

Friday, August 08 2008         2 Comments

Anybody who's talked to me about web programming in the last 5 years or so knows that I'm a big fan of caching.  However, in most of my presentations on ASP.NET caching, I don't get into the client side of things.  Mainly this is because ASP.NET is a server-side technology and there's plenty of cool stuff to talk about on the server with regard to caching, and I truly think that's where the biggest performance wins are to be had (i.e. reducing expensive calls to databases and web services).

That said, a lot of bandwidth can be saved and the perceived performance of individual pages can be greatly improved with some client side caching.  What I mean by client side is within the user's browser, or at the very least, at some proxy server nearer to the user than your web server.  The way web servers and browsers determine whether or not to cache a particular request is by inspecting what headers are sent with it.  The two most important headers (for caching) are Expires and Cache-Control.

Cache-Control determines whether or not the content should be cached at all.  If it is set to private, then intermediate servers like proxy servers will not cache the content because it is (supposedly) meant for a particular user only.  For instance, you wouldn't want to send user Alice her bank account details and then have user Bob make a request to your bank web site through the same proxy server for the same page and have him get back Alice's account details.  However, some things you're perfectly happy to let proxy servers cache, such as perhaps your 25kb logo that's on every page of your web application.  By making its Cache-Control header public, proxy servers may choose to keep a local copy of that file rather than re-fetching it from your web server with each request, saving on both bandwidth and latency.  Further, browsers may cache the file as well.  In practice, this varies with the browser and it usually helps if you also set the Expires header.

The Expires header should be set to a date, and as long as that date has not passed, proxy servers and browsers may decide to cache the contents of the request locally.  Sometimes requests will be made for the content if it has been modified (using the If-Modified-Since header) in which case the server may choose to respond with a Not Modified 304.  This still incurs round trips to the server, but the response only has headers, no body, so it uses minimal bandwidth.  This allows browsers and proxy servers to periodically check to see if a resource has expired without having to refetch it in its entirety.

A useful tool for checking the cacheability of various URLs on your sites is http://ircache.net/cgi-bin/cacheability.py.  This tool will let you see the headers that your resources return and will give you a graphical indication of the cacheability of the resource (green means cacheable; red means not so much).  As a best practice, I recommend making all images immutable* and setting their Cache-Control to public and Expires to a far future date, such as "Sun, 17 Jan 2038 19:00:00 GMT".  If the image needs updated, it should have a new URL and all references to it should be updated.  This will ensure images are cached as effectively as possible and ensures that updates to images take effect immediately without waiting for various proxy servers to update their caches.

*Here I'm using immutable to mean that, once uploaded to a particular URL, the contents of the image never change.  Obviously this only applies to static images, and not to dynamic charts, etc.

I've also recently been using Amazon S3 more and more, and have found that Bucket Explorer is a nice tool to use with that service.  Here's a nice tutorial on how to set headers of resources within S3 using Bucket Explorer.  Using S3 to host images is also nice because every bucket is a different subdomain (e.g. bucket.s3.amazonaws.com) and so with a couple of different buckets for images, css, javascript one can easily have 3 or 4 different domains involved in the loading of resources for a given page (with all static files coming from S3).  Since browsers typically only open 2 requests to a given domain at a time, this means you'll be able to utilize 8 simultaneous requests for content (best case) which can enable your page to load 4x faster than if it had all of its resources on a single domain (and only 2 simultaneous requests).

More Resources

Using S3 as a CDN (Content Delivery Network) Part 2

 

SQL Server 2008 Ships

Wednesday, August 06 2008         2 Comments

Microsoft has released SQL Server 2008 officially, according to this press release.  The software is currently available to MSDN and TechNet subscribers:

SQL Server 2008 is now available to MSDN and TechNet subscribers and will be available for evaluation download on Aug. 7, 2008. SQL Server 2008 Express and SQL Server Compact editions are available for free download today at http://www.microsoft.com/sqlserver. As previously announced, pricing for SQL Server will not increase with SQL Server 2008. More information is available at http://www.microsoft.com/presspass/presskits/sqlserver.

Read the full press release for more details, or hop out to MSDN and begin downloading now before everyone else does!  Oh, and check out the new UI for the MSDN subscription center, too - the filter is awesome!

MSDN Subscriptions

DevExpress Earthquake Video

Thursday, July 31 2008         No Comments

DevExpress is one of several companies I work with via Lake Quincy Media, and it seems like a very fun place to work.  Recently they launched a video site to help showcase their products, and earlier this week they made a video showing the reaction of some of their employees to the 5.4 scale earthquake in LA earlier this week.  Check it out, and then check out some of their other videos as well.

Incidentally, Mark Miller (Miller in the video - the bald one...) also has his own blog and spoke at this year's TechEd.  He's the brains behind CodeRush and Refactor and is a good guy to keep tabs on if you're interested in optimizing your coding experience (though he's not much of a blogger).  He also participates in the show Mondays with some very funny stuff.

There are no single developer projects

Tuesday, July 29 2008         10 Comments

Oren wrote today, There is no such thing as a single developer project.  At first this sounds like an obviously false statement, but read on:

There are always at least two people in any software project:

  • The developer who wrote the code.
  • The developer who read the code.

They are never the same person, even if just by temporal dissonance.

This is a very clever thing to point out, and worth remembering when you're tempted to take shortcuts using the excuse "I'm the only one working on this code so I can wing it."  Who you are today is not who you were yesterday, nor will you be the same person tomorrow.  Write your code with the knowledge that someone else is going to have to maintain it, even if that someone else is you with a bit more experience (and probably a bit of lost knowledge about the details of what you're working on right at this moment).

Batch JavaScript Libraries for Increased Performance

Monday, July 28 2008         3 Comments

I've been meaning to set up batched loading of the JavaScript libraries used by Lake Quincy Media's administration application for some time, and finally had a chance this past weekend.  The site uses a variety of third-party tools such as DevExpress, ComponentArt, AJAX Control Toolkit, Overlib, PeterBlum, Dundas Charts, and probably a couple of others I'm forgetting at the moment.  As a result, the site's initial load tended to be pretty sluggish.  JavaScript libraries are loaded and executed serially by the browser, resulting in a pretty significant bottleneck to page load time, as shown here:

image

Once loaded the first time, most of these scripts are cached in the client, so performance doesn't remain dreadful (and usually the individual files don't take as long as they are above).  However, you can see how this has a seriously detrimental effect on the site's perceived performance, and this has nothing to do with any kind of server or database processing time (which is typically the first place folks go looking for performance issues within ASP.NET applications).

While researching this problem I found a couple of helpful links:

More importantly, though, I discovered that the AJAX Control Toolkit project added a new ScriptManager object over a year ago that I'd overlooked.  David Anson blogged about the new ToolkitScriptManager class last June, explaining its script combining features.  Replacing my ScriptManager with this one resulted in an immediate and significant reduction in the number of ScriptResource.axd calls required.  The ToolkitScriptManager inherits from ScriptManager, so you simply need to replace <asp:ScriptManager /> with <ajaxToolkit:ToolkitScriptManager /> assuming your prefix for the AJAX Control Toolkit is ajaxToolkit.

It's a good idea to use a separate domain for static files like images, CSS, and common scripts, because browsers typically will open 2 concurrent connections per domain to retrieve such things.  However, in the case of scripts like these, the browser only loads them one at a time, and further since they're dynamic (at least, the *.axd ones), there's no simple way to use a separate domain anyway.

After switching to ToolkitScriptManager, I still had a bunch of dynamic script calls, which I determined were being loaded by ComponentArt controls.  I figured they probably had a similar batch load mechanism, and they did not disappoint.  Milos wrote about Optimizing Web.UI Client Script Deployment, which has the necessary steps.  It requires setting up a handler and adding a key to <appSettings /> (something which I think is a bad idea for components to use), but otherwise it was quite painless.

Finally, I determined that the Overlib scripts we're using were only needed by one custom control we'd created for displaying Help dialogs, but the scripts were being included in the Master page.  Many pages show the help dialogs, but many do not, and there were 4 separate scripts being loaded.  I could have written my own handler or updated the custom control to automatically emit the required script references, but since I was going for the simplest thing that worked I opted to wrap the 4 <script /> tags in an ASP.NET Panel control and set its visibility to a property on the common base page.  I then set this property to true from my Help control's Page property, after casting it to our base page class using the as keyword to ensure type safety.

The end result is shown here:

image

The scripts are still loaded serially, but there are far fewer of them, so the overall page load time is dramatically reduced.  In this case I had to look at three different approaches for three different sets of scripts that I was using.  However, it's possible to use an HttpModule to look at all of the resources on the page and batch them up into fewer requests.  The links I listed above show some of this, but if you want an off-the-shelf solution, check out the Runtime Page Optimizer from ActionThis, which will do this and more.  The product is still in beta, but it offers 9 different page load optimizations that take script, css, and even images and batch them up on the server and request them as fewer, larger chunks on the client.  I've tested it and it's not quite 100% ready to go for my needs, but that's mainly because of some conflicts with the many different third-party tools I'm using.  On simpler pages, it just works, so check it out if you want a simple solution to batching up scripts and other files to improve performance of your web application.