So I'm sitting here in southern California making some final preparations for my talk this evening at the South Bay .NET UG.  I ran into a wacky scenario where my event handlers for my silverlight components weren't firing.. So after verifying it wasn't just a silly coding error (which I'm certainly not immune to) I decided to 'clean up' my dev environment.  I had installed the IE8 beta the other day, so I started by uninstalling that.  I was also running on one of the pre-release Silverlight 2 Beta 2 builds, so I figured this would be a good time to bump up to the actual bits. 

I ran the uninstall, and downloaded the new chainer.  BTW, 86mb feels like you're downloading the whole world when you're running off of Hotel wifi.  So with my 86mb chainer downloaded, I ran the installer.. That's when everything went wrong.

The new Silverlight 2 Beta 2 installer has a prereq for Visual Studio 2008 SP1 (which was JUST released).  I hadn't yet installed VS2008 SP1, and was still running one of the final SP1 beta's.  So of course, I had to first uninstall the SP1 beta.  If it were only that easy.. the removal tool requires that you have the original VS2008 install media handy, which of course I did not.  I finally convinced a co-worker to share a cdrom with the bits on it back at the office, and I connected via VPN. 

Sounds like a success, right?  Wrong.  This has got to be the slowest install/uninstall I've ever experienced.  I'm sure working off of crummy wifi and through a VPN network share isn't helping..  At this point, I'm just hoping I have a functioning Visual Studio for this evening - forget about the last minute tweaks to my code..

The moral of the story is - don't decide to install or uninstall software while on the road, especially when you don't have access to a high speed internet connection.  You never know what 'chain' of events you may have just started.

Web development is all about breaking up your application into pieces. Multiple pages make up a site.  UserControls are used to break up pages into smaller pieces, and custom libraries are often used for either framework value, or as GUI libraries.  Any time you start working with these scenarios, assemblies and references are going to start to enter the equation. 

In a perfect world, assembly references would be easy, and in many cases they are.  But what happens when you need to support more complex scenarios?  I happen to live and breathe components, working for a UI tools company, so I run into these questions every day. 

Yesterday, I had a customer who needed to get an update for a bugfix, but wanted to limit the exposure (and regression testing) by applying the fix to a single page (or component) rather than the entire site.  I happen to think this is a great idea and can dramatically reduce 'risk' when updating software. 

Solution 1: Binding Redirects

Applying an update for a single assembly is easy to do, except when you have to start worrying about shared references.  For instance, the Infragistics tools have a common "Shared" assembly that acts as the framework library for all other assemblies.  When you want to update a single assembly (Infragistics2.WebUI.UltraWebGrid.v8.2 for example) you need to also update that assemblies referenced assemblies - specifically the "shared" assembly.  But what about the other assemblies?  If you replace the "shared" assembly with a new version, the other assemblies will no longer load since they can't find the version they were originally compiled with.  This is where binding redirects come into play. 

A Binding Redirect is a way to tell the fusion assembly loader that even though an assembly with version a.b.c.d is being requested, load a.b.c.z instead.  I've covered this topic before in my Surgical Hotfixes with Binding Redirects post.

Binding Redirects are great if you want to update an assembly reference for your entire site, but in many cases this is still too broad of a change.  There must be a way to apply an update to a single page - right?  Luckily, the answer is yes.. but there are a few requirements.  First the solution.

Solution 2: Page Specific Web.config file

Web.config files have the great ability to cascade through your site, so you can put a web.config in any folder.  The Web.config file is also where you specify assembly references - how convenient!  The trick is to specify assembly references specific to a page by creating a web.config for your 'special' page.  Which brings us to the requirements.

You must put your 'special' page in its own directory since web.config files are organized at directory levels.  You also must use the GAC for your assembly references.  This was where I got tripped up.  I had my original assemblies in the bin and tried creating a second page with it's own web.config all set up perfectly.  The visual studio compiler doesn't like this, as it will automatically load the assemblies in the bin directory and give you the CS0433 error upon compilation.  Once I deleted the local bin assemblies everything was happy. 

Here's an example of a subdirectory web.config file -

image

And here's what my website looks like

image

Microsoft is about to ship Visual Studio 2008 SP1, and .NET Framework 3.5 SP1.  Now service patches aren't always very exciting, but these are because they contain some great new features.  You've probably already heard the buzz around AJAX History support, and Dynamic Data.  Script Combining is also part of SP1, and it's something that you should certainly be interested in.

So why is script combining is important?  ..it's all about network latency.  Conventional thinking was to break apart script files into small chunks so that the browser only needs to download the minimal set required.  The idea was great, and it could even have a positive impact on your application, until the laws of the internet start to interfere.  The problem is that each script file must initiate a connection to the server.  Connections have some degree of overhead involved from the aspect of the server, so splitting a file in 2 and serving it up over 2 requests instead of one, will take slightly longer.  But that's nothing compared to the effects of network latency.

Latency, is the minimum time it takes for a packet to travel from one location to the next.  We're all familiar with the idea of latency, as it's clearly evident when you're speaking on the phone to someone across the world.  Think of the delay before they hear what you said, and vice-versa.  The same laws of physics apply to HTTP connections.  For HTTP, the latency is assessed per connection.  So for every connection your site makes back to the server during a page load (or partial AJAX load), your load time increases by a given number.   If we go back to our phone conversation analogy, there's no noticeable delay while you're talking, but think about what happens each time you stop talking and wait for a response from the other side.  Those delays are all additive, just like in our HTTP request/response pairs. 

To put this to some hard numbers, imagine your site has 30 'objects' on the page.  An object is something that requires making a connection to the server - this could be a javascript file, an Image, a flash video, or even a stylesheet.  Now let's imagine some unfortunate soul on the other side of the world is viewing your site, or running your web application.  If their average latency is 300ms, you're talking about a minimum page load time of 4.5 seconds based on the browsers ability to have 2 simultaneous connections (300ms/roundtrip * 9 connections /2 connections per roundtrip) = 4.5 seconds

If you want to simulate this in an ASP.NET application, add a HTTPModule to your application and insert a System.Threading.Thread.Sleep(300) into the BeginRequest event.  Now for each request made to your application, there will be a 300ms delay representing the latency.

Caching Effect on Latency

So what about the effects of browser caching?  Javascript files along with CSS and Images are all cached resources for a browser.  As long as these items are in the browse's cache, the client does not need to initiate a request (http connection) with the server, which means no latency penalty is incurred.  Tip: When setting cache headers, remember that using a conditional request (If-Modified-Since header) will still require an HTTP connection.  Stick with Expires or Cache-Control headers, which will alleviate the need for any HTTP connection once the item has been added to the cache.  Learn more about caching from w3.org. You can set the cache characteristics of specific filetypes through your webserver, or by adding response headers dynamically. 

A recent study published from yahoo though, shows an astonishing 20% of page views are done with an empty cache.  While that number seems high, it certainly points out that empty cache visits are not edge case, and should be given some attention.  Besides, we all know how important first impressions are, so even if your application only loads slow the first time a user visits, that may also be the last time.

Taking Action

It should be pretty clear now that latency has a significant impact on your web site/application performance.  And the to make matter worse, it's not something that you're likely to notice during testing since your latency will be minimal.  That's why defensive programming is a priority here.  And it's not that difficult either..

Step 1 - Analyze.  Download an HTTP monitor like Fiddler (http://www.fiddlertool.com/fiddler/version.asp)  Use the tool to examine how many connections are made during an empty and full cache request. 

Step 2 - Minimize Connections.  Minimize the total number of HTTP requests by combining separate script or css files into a single file.  There are utilities out there to combine CSS files and even shorten class names.  If you're using ASP.NET 3.5 SP1 you can combine Javascript resources by using the ScriptManager's CompositeScript element.  Simply add each script element as part of a "CompositeScript" and the ScriptManager will do the combining for you.  This is especially useful when you're using 3rd party tools which may contain embedded resources, and there's no actual script file to work with.  If for instance you're using NetAdvantage for ASP.NET and have made use of the WebGrid, you can combine the multiple script files into a single through the following CompositeScript block:

<asp:ScriptManager runat="server" ID="sm1">
    <CompositeScript>
        <Scripts>
            <asp:ScriptReference Name="MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Name="Infragistics.WebUI.Shared.JS.ig_shared.js" Assembly="Infragistics35.WebUI.Shared.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid_dom.js"
                Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid_cb.js" Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid_an.js" Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid_kb.js" Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid_xml.js"
                Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
            <asp:ScriptReference Name="Infragistics.WebUI.UltraWebGrid.js.ig_WebGrid.js" Assembly="Infragistics35.WebUI.UltraWebGrid.v8.3, Version=8.3.20083.1, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

The best part about this type of performance tuning is that you can figure out the exact performance gains you will achieve before you begin making any changes.  Even better, by reducing the number of requests for each user, you're reducing the load on your webserver as well.  If you run Fiddler again at this point, you will see that in the place of these 9 separate javascript files, is a single script file with whitespace removed.  In our example above with a 300ms latency, you've just shaved almost 2 seconds off of your page load time.

As one final note, if you're using NetAdvantage, be sure to get the latest hotfix once SP1 has been released (RTM) in order to take advantage of Script Combining.

Build A Cool Silverlight Control, Win Free Stuff!

stacked_small_slbc_08There's a really cool contest going on right now, promoting both Silverlight and open source.  If you check out Silverlight Control Builder Contest '08 over at gosilverlight.org, you can read up on the details.  To state it simply, build the coolest Silverlight control, and win some great stuff including NetAdvantage for .NET (ASP.NET and Windows Forms) + NetAdvantage for WPF.  Additionally contest winners are entitled to NetAdvantage for Silverlight once it ships.  All in all, there are thousands of dollars in prizes available, all to reward you for building cool stuff and sharing it with others.  

So check out the contest details, but even more importantly the prizes

And if building controls happens to turn into a full time love affair for you, shoot me an email.  I just may be able to hook you up with your dream job...

I know, I'm a little late on this announcement - but this has been one crazy summer!  Ok, we've officially only been in summer for less that a week, but considering the temp was 98 degrees when I got back from TechEd a couple of weeks ago, I say summer has been with us for a while. 

Anyway, back to the release.. After another 4 month cycle, there's some really great stuff that has been added to NetAdvantage for .NET.  Here's a quick rundown of the new features. 

 

Windows Forms

WinValidator

This extender control can be used to perform validations on input fields in your app.  Classically seen in ASP.NET applications, validators make it quick and easy to accomplish certain scenarios while improving the overall user experience by providing real-time feedback. 

image

In the example above (included in the samples SDK) I've demonstrated using a balloon tip style message to show that this was a required field. 

 

Row Edit Template for WinGrid

Editing tabular data doesn't always have to be reminiscent of your favorite spreadsheet application.   You can use the Row Edit Template to modify the editing experience of a grid row.  Because this is a template, you have total control over appearance and functionality.  The edit template can be displayed directly beneath a row (as shown in the image below), or it can be 'detached' and positioned exactly where you'd like.  The net effect... happy users.

image

 

Suggest mode Typeahead

Typeahead has evolved through the years..  I'm sure you can remember the days when a dropdown first allowed you to type in a letter and scrolled through the list automatically for you.  Next came multi-character typeahead, where words would actually be completed for you.  So how do you make that better?  Easily - live filter the results based on the characters being typed in.  Using the new Suggest AutoComplete mode, you can provide your users with a much improved interface for picking from a list of values.  This behavior is commonly seen today with search engines, where they will begin to show you search suggestions as you type. 

image

In the example above, typing "A" into the combobox the user is prompted with the 3 choices displayed in the dropdown.

 

Visual Studio 2008 Docking Indicators

For those of you who have moved up to VS2008 (and I'd recommend that move to anyone!), you've likely noticed that Microsoft updated the docking indicators once more.  But fear not, we've added the 2008 style to our DockManager as seen below.

image

 

ASP.NET

 

TreeMap

Ever need to show hierarchical data in a visual way?  That's the sole purpose of the TreeMap.  If you're not familiar with TreeMap, you can get a great explanation and some common examples from Wikipedia.  An example of a TreeMap is shown below.  BTW, this new visualization type has been added to the UltraChart (win and web).

image

 

WebSlider

I personally, am tired of textboxes.  It seems that every time an application wants me to enter data, I have to use a plain old standard textbox.  Enter the WebSlider.  You can use the WebSlider to enter a single value, or a 2 value range.  And the user never has to type in a single character.  The 'data entry' is done entirely through the needle movment, which just feels better.  This is perfect for touch screen devices, where pointing and clicking is much more natural than typing.

image

The example above, taken from the new InfraRealty showcase sample uses the WebSlider to set a min/max value as a range for search criteria.  Personally, after seeing how natural this implementation felt, I wish that all of the RealEstate sites out there would update their UI's!

 

WebHierarchicalDataSource

At the risk of sounding like a car salesman, I'm going to give you my honest opinion on this control - it's the bomb.  Not only can you set up hierarchical relationships at design-time, it does the CRUD for you as well!  No more worrying about how to update your hierarchical data when bound to the webgrid, just use the WebHierarchicalDataSource (WDHS from here on).  How about self related hierarchies?  This is a pain point for some of you I know, as you've been asking for this type of support for the grid for as long as I can remember.  The WHDS is here to relieve your pain.  You can set up your self related hierarchy in the WHDS, and then bind it to the WebGrid.  The WHDS is built on top of Microsof'ts datasource control framework - so the WHDS can be used to bind to anything that can consume hierarchical data (ie. trees and menus). 

image

Above, the WHDS designer is being used to create a 2 level hierarchy, taking info from two separate DataSources.  Note that you can take data for any level, from any datasource.  So if you wanted to map your LINQDataSource data to parent data coming from your SQLDataSource - it's a simple task.

 

You can download NetAdvantage for .NET 2008 Volume 2 (in various packages) from the download page, and begin using these new features today. 

I've written about moving the <%@ Register TagPrefix ... %> directives out of your ASPX pages, and into your web.config.  But one thing I never talked about was - how to do that step.  I always did it manually, but about a year ago, I remember talking with one of the developers on the Project Upgrade Utility.. Well, that discussion to my surprise spawned off a lovely feature..  So here's the simple 2 step process

1) Launch the Infragistics Project Upgrade utility

image

2) Open the options dialog by click on the File menu, and selecting the Settings menu item.  In the options dialog, check off "Add register tags to web.config" (optionally, choose "Add  all assemblies to web.config" which will add assembly references as well).

image 

After saving your settings, the next time you run the Infragistics Project Upgrade utility, it will remove all Infragistics <%@ Register .. %> directives from your ASPX pages, and replace them with the appropriate TagPrefix nodes in your web.config.  Using the settings above, the upgrade utility will also add all Infragistics assembly references to your web.config. 

image

Well, it finally happened.. my PDC 2005 laptop bag started to tear apart at the seams.  It took me about a week to finally choose its replacement.  I had was looking for three things.  It had to look good for one.  For the amount of time I carry my laptop around with me, it's almost like a fashion accessory.  My second requirement was that it was small.  With the amount of traveling I do, the last thing I want is a big clunky bag.  My final requirement was that it looked professional enough for me to comfortably take it into business meetings without being embarrassed.  I finally decided on the Case Logic bag.

When the bag arrived my first impression was that it was bigger than I thought it would be.  But the canvas fabric was an improvement over my last bag.  The bag itself doesn't have much structure, so with out any contents in it, it shrinks down nicely.  When it came time to move the contents of my old bag to the new one, I was happy to see that there was plenty of room.  My only complaint is that there's no good single pocket organizer like there was in my PDC bag.  There are a few different pockets, but they're just large pockets with no separators/organizers in them.  I was still able to organize my things to some degree, so it wasn't a total loss.  The strap feels a lot more sturdy than the PDC 2005 bag did.  Its a wider strap, so it doesn't have the tendency to cut into your shoulder. 

The bag is a little more faded than it looks in the picture, and the graphics aren't as crisp.  I'm glad the graphics aren't as crisp, because I was worried they were a bit too 'busy'.  I tend dislike the whole idea of "street art" on mainstream items anyway.  It's like putting flame stickers on your car's hood.  If you got a good flame job from a quality paint shop, it just feels different than the stick on one sold at the local auto parts store.  Anyway, back to the laptop bag.. All in all I give it a 7 out of 10. It's close to what I wanted, but not exactly.  But for $30, I can't complain at all.

I'm finally back from Orlando, or at least I think I am.. but the weather here in NJ isn't the beautiful 75 degrees it was when I left, it's the 95 degrees that I was hoping to leave in Orlando.  Oh well, it's still good to be home.

TechEd was a blast.  I flew down on Monday night, and went directly to Glo for the kick-off "Party with Palermo".  When that finished up (around 10:30pm), I ran over to Hooters to watch the end of the hockey game, and get some dinner.  Well, all of you hockey fans know that I got to see much more than the last few minutes..  the game went into OT, and we hurried back to the house to watch the end of the game.  A 20 minute drive later, and we still got to watch 2 periods of playoff hockey. 

Tuesday morning was a little rough.  Not because we stayed up late to watch hockey, but because we stayed up even later to finish the wings and beer.  Luckily, everyone got up on time, and we headed over to the convention center to start our long day.  As expected, we went through just about every T-Shirt we brought, on Tuesday night.  The Infragistics t-shirts for this show were actually pretty cool, and didn't scream "tradeshow".  I forgot to grab one for myself before they were all gone - hopefully we have some left at the office. 

Wednesday through Friday is all pretty much a blur.  Not because of the alcohol (though I'm sure that played a part), but because I was so busy.  I did a Birds of a Feather (BOF) on Wednesday night, and it was pretty cool.  It was the first time I attended, let along moderate a BOF, and I'm looking forward to doing more of them.  The audience participation was great, and we had some much needed discussion around ASP.NET security.  Thanks for everyone who attended. 

Saturday finally came, and it was time to head home.  But before boarding my flight, I had to take care of one last thing - the teched 'tweener'.  Snuggled in the weekend between the two weeks of TechEd, the Florida .NET community got together for a code camp.  I did a morning session on Saturday covering LINQ and the LinqDataSource for ASP.NET.  The session was surprisingly full for a Saturday morning, and the crowd was eager to participate, which made it easy for us all to have fun (and stay awake).

That's my TechEd wrap up.  If you didn't get a chance to stop by the booth and say hi, be sure to catch me next time.  And Wally - my apologies for running out on you .. had a plane to catch.  We can sync up another time.

That seems like a long title, but now that TechEd is cut in two, I wanted to be sure we were all on the same page.  If you're going to be in Orlando next week, you'll likely run into some Infragistics shirts while you're there.  We've got quite a few people heading out there.  Here are some ways you can meet up with me/us

Party With Palermo - Infragistics is sponsoring the party this year, and we'll be there handing out some cool stuff as you walk in

BOF - What's a BOF?!  A Birds of a Feather session is an open forum for discussion.  I'm heading up a discussion on ASP.NET Security (focus on AJAX) on Tuesday night at 4:30.  Stop by and participate in the discussion, or just listen to what everyone else has to say!

Infragistics Booth - Booth # 1208  I should be there for most of the show, so when the show floor is open, drop on by.  We've got some killer t-shirts this year, so I'd recommend stopping by earlier rather than later.  I don't expect the shirts to last past Wednesday night.

Last year Infragistics won a Jolt award for Libraries Frameworks and Components, and that was a new level of achievement for us.  This year, I'm excited to announce that we've won a Codie as well for Best Software Development Solution.  Now don't get me wrong, I'm happy about any award we win, but there's something to be said for privately judged awards.  Not that I don't enjoy campaigning every year for the 'popular vote' awards, but I tend to find that the results rarely resemble real life.  Or maybe they do resemble real life ala the amount of free time some folks have to vote for themselves :)  Either way, I think this is really cool, and another milestone achievement for Infragistics. 

Quick story about the Jolt award..  When we found out we won, we had to get someone off to the west coast in 2 days to accept the award.  I was on the short list of ppl to go, but was already scheduled to be traveling somewhere else the next day.  As luck would have it (or not, depending on who you ask) Chris Lukose our corporate trainer was stuck on the west coast because of a snow storm here on the east coast.  And he wasn't alone, we had about 5 people stuck out there.  3 of them somehow ended up in Las Vegas, but that's a whole other story.  Long story short, we convinced Chris to stay even longer and accept the award.  Thanks Chris - I owe you one :)

More Posts Next page »