Archive for February, 2008

10
Feb

West Without A Word

Music has been a huge part of my life for as long as I can remember. When I was 18 I was writing for 6 different magazines, spending all my time interviewing bands, reviewing albums, and writing feature articles. It was tiring and sometimes very frustrating, but I met a lot of awesome people and got to be involved in a lot of very cool things that I’ll never forget. I’ve made friends with hundreds of record labels, publicists, and bands, spanning numerous genres. I’ve yet to make a dime for any of my work, but the beauty of being involved in the DIY music scene is that money isn’t the motivating factor,which is why I love it so much.

As I’ve gotten older I’ve been less and less involved with the independent music community because I just haven’t had as much time as I used to. I’ve been involved with numerous other magazines over the years, and I’m always dabbling with some side project and keeping in touch with all my old contacts. The last couple years I’ve been co-running an e-zine called The Silent Ballet that focuses primarily on independent instrumental/experimental music (i.e. post-rock, IDM, electronic). They’ve done a lot really influential things for that scene, and have become the best resource out there for fans of the respective genres.

Living in Florida didn’t lend itself well to the type of music I was listening to because many of the bands I liked couldn’t afford to make it out there for one reason or another. I found myself having to travel out of state to have the opportunity to finally see a great live show. As cool as taking mini-vacations was, it was expensive to do that just to see one or two bands. My plight gave me the idea of organizing a music festival in large cities where instrumental music is prevalent. That way people could make one trip and see a lot of great bands they wouldn’t normally be able to.

After months of planning and numerous attempts, the inaugural show will be taking place in Los Angeles. It will feature 10 bands from the California/Arizona area, spanning two of the coolest venues in LA. My hope is that it will attract lots of fans from out of state who were looking for an excuse to take a mini-vacation and love this style of music. It’s an experimental project, that has been fun setting up and will no doubt be an awesome experience. If anyone is in the LA area and wants to check out some new independent artists, this should be worth your time :)

festival-4-urban_sky_modified_by_fls-copy.jpg

09
Feb

Series Update - Live Samples

I was chatting with the one and only Scott Hanselman earlier today and he gave me the suggestion of hosting the sample demo used in my AJAX History series so readers could easily see right away how it works without having to download the code and run it (that can be more trouble than it’s worth).

Of course his advice was great, so I went ahead and setup a new domain (playground.lostintangent.com) and put up the quarterback rater app. You’ll notice the link to the live sample is on the landing page for the AJAX History series. From here on out I will be hosting the samples like this and publishing the link to them from their respective series pages.

08
Feb

Training Series Reorganization

I just wanted to briefly let everyone know that I’ve reorganized how I’m aggregating my training series. Previously on the right side navigation there was a link specifically for the ADO.NET Data Services series, but I’ve ripped that out and replaced it with a link to the overall Training Series page. This page aggregates all training series, which in turn aggregate all articles in their respective series. Also notice that I’m placing the series code on the series landing page rather than within each individual article. For example, if you look at the ASP.NET AJAX History series page you’ll notice the green box with the solution download. This will be a provision for all series moving forward. As a new article in posted in the series, the series solution will be updated to reflect the new article.

My goal is for the training series page to be a nice one stop shop for finding entire training series for specific features as well as be a view into what is coming up. Along with article links and code download I’m also going to post screencasts to individual series page as well. Basically any resource that I produce around a specific feature will be published to its training series page for easy consumption.

Any feedback you have please let me know.

08
Feb

ASP.NET AJAX History Part 3: Server-Side + Client-Side

Having the option to manage AJAX history from both the server-side and client-side lends itself really nicely to being able to accomodate a large number of situations. If you’re looking to add some history functionality to an existing web page that was developed using server controls, it is pretty painless to drop in a ScriptManager and UpdatePanel and go off on your merry way. If you’re creating a web page from scratch and you’re looking to get as streamlined as possible, then using the Sys.Application class in the ASP.NET AJAX library can make all of your history dreams come true. Unfortunately it isn’t always that cut-and-dry though, and sometimes a single application, or even a single page, might have multiple peices of functionality in it that have different needs. The question that arises is this: can both history approaches be easily leveraged within the same application or page and functionality properly? The answer to that can be derived from a 70’s English rock band:

yeslogo1.jpg

Not only can the two approaches co-exist, in many ways they feel like they were meant to live together. Remember how it was mentioned that in the state URL all server-side history points are appended after a double ampersand whereas all client-side history points preceed the ampersands? That fact alone makes the intermingling of the two to successfully work.

What we’re going to do is take both versions of the quarterback selector app (client and server editions) and mash them together onto the same page. We’re not even going to touch a single character of code. I’ve added some extra text and HTML to make the overall demo look a little more compelling. If I run the app, this is what we’ll see:

lit-2-7-2008-34116-pm.png

This should obviously look pretty familiar to you by now. The client-side portion is 100% JavaScript code, while the server-side porition is leaning on the ScriptManager and UpdatePanel server controls. What would you expect to happen if we began selecting quarterbacks from both lists at the same time and then trying to use the back and forward buttons? If you are the type of person who doesn’t like to take risks I would recommend you stop reading here. If you are completely insane and love living life on the edge, the continue reading because extreme awesomeness is about the ensue.

Let’s start by selecting a quarterback from the client-side list to make sure it still works. Let’s go with David Garrard:

lit-2-7-2008-34157-pm.png

So far so good. Let’s now try to select a quarterback from the server-side list to ensure that implementation still works. Let’s go with Brett Farve:

lit-2-7-2008-34322-pm.png

Alright so both implementations seem to work beautifully, but that doesn’t prove that our history is working. I notice that my browser’s back button is active which makes me wonder what will happen if I click it’s pretty blue little face. What do you think?

lit-2-7-2008-34522-pm.png

Is that cool or what? The back button undid the last action, which in this case was the server history point, but didn’t affect the client history point. You might have originally thought that hitting the back button would have removed both selections, because it would be backing out of both the client and server side history “buckets”. So how does this work? I’m going to hit the browser forward button to redo our server-side selection and then examine the current URL:

http://localhost:49652/#FavoriteQuarterback=David%20Garrard%20&&FavoriteQuarterback=Brett+Farve

Doesn’t get much clearer than that. You can easily see the two history points seperated by client/server. The point before the double ampersand is the client history point and the one following the double ampersand is the server history point. What that means is that I could bookmark my page right now and when I return it will recreate both selections. Because the URL contains state information for both the client and the server approaches, the ScriptManager’s Navigate event will be fired as well as the Sys.Application class’s navigate event. I think that is just too cool. I could sit here and click on both lists all day long, repeatedely hit the back button, and then watch it undo every one of my selections from each list individually. I would recommend going crazy with it, it really drives the point home just how awesome this is.

At the conclusion of this three-part series on ASP.NET AJAX History, hopefully your minds are running wild with ways you can begin implementing it into your applications. While this may not be the most groundbreaking feature to be released this year, it certainly shouldn’t be thrown to the wayside. It’s a very powerful little feature that can really increase the useability of a web page for a user with little effort from the developer.

07
Feb

ASP.NET AJAX History Part 2: Client-Side

Now that we’ve gone through the basics of the ASP.NET AJAX History feature and seen how it works server-side, we’re better equipped to see how to leverage this functionality from a client-side perspective. The last article highlighted the easability of adding AJAX History in circumstances where using the UpdatePanel makes sense, but in pure AJAX applications, that kind of logic needs to be achieved via JavaScript, which the previous article didn’t satisfy. Luckily, all the behavior that you saw in the last post can be fully replicated using the ASP.NET AJAX libraries. The second part of this series will show how to develop the exact same application as we did in part 1, but doing so completely on the client-side. We’re going to be adding the new functionality to the same page as the last article, and as such, reusing the existing code (ScriptManager, CSS, etc.)

We begin by creating the same list of quarterbacks that we saw in part 1, but in this case we’re not going to use a server control, but rather straight HTML:

lit-2-7-2008-93548-am.png

If I ran this right now I’d see the following:

lit-2-6-2008-41754-pm.png

Notice that we don’t have to deal with LinkButtons as we did in our last article, but rather we just have a nice and simple unordered list. Now we need to enable the ability for users to select their favorite quarterback. Since we can’t lean on the BulletedList control’s Click event, we’ll have to write some JavaScript code. We’ll add a new JavaScript file to our project, and reference it using our ScriptManager:

ajaxupdate.png

Keep in mind that the EnableHistory property also applies to client-side history, so make sure you have that set to true regardless which approach you take (client/server). The EnableSecureHistoryState properperty however does not apply to client-side history, so make sure you only store trivial data in history when using the client-side approach. Let’s add some initialization code to make the list selection work. We’ll add the ubiquitous pageLoad method to our new script file:

var quarterbackItems;              
 
function pageLoad() 
{ 
    quarterbackItems = $get("quarterbacks-list").getElementsByTagName("li");              
 
    for (var i = 0; i < quarterbackItems.length; i++) 
    { 
        $addHandler(quarterbackItems[i], "click", quarterbackClicked); 
    } 
}

All we’re doing here is grabbing the list items from our quarterbacks list and wiring up their individual click events. The logic for the quarterbackClick method looks like so:

function quarterbackClicked(e) 
{ 
    var name = e.target.innerHTML; 
    selectQuarterback(name); 
}

We’re just grabbing the inner content (the quarterback’s name) of the item that fired this event, which is the list item, and then calling a method called selectQuarterback, passing it the selected quarterback’s name. The code for the selectQuarterback method looks like so:

function selectQuarterback(name) 
{ 
    for (var i = 0; i < quarterbackItems.length; i++) 
    { 
        var element = quarterbackItems[i];             
 
        if (element.innerHTML == name) 
        { 
            Sys.UI.DomElement.addCssClass(element, "selected"); 
        } 
        else 
        { 
            Sys.UI.DomElement.removeCssClass(element, "selected"); 
        } 
    } 
}

Here we’re simply looping through every list item in the quarterbacks list and marking the proper item as being selected and ensuring that any previously selected items are unselected. You should notice that the logic for this exercise is practically 1:1 from the previous article, we’ve just ported it to use JavaScript and the ASP.NET AJAX libraries. We’ll reuse the same stylesheet from the last post since we’re leveraging the same HTML output and class names. If I were to run this right now and click on Tom Brady, I’d see the following:

lit-2-6-2008-42534-pm.png

Since we’re reusing the same stylesheet from the last article, this looks exactly like before, only without the LinkButtons. If I select Carson Palmer I’d see the following:

lit-2-6-2008-42644-pm.png

So it’s clear that our app functions perfectly now. Unfortunately, regardless how many times I select a different quarterback I still don’t get any love from my back and forward buttons:

lit-2-6-2008-45536-pm.png

Up to this point we’ve just created a neat little JavaScript app. The browser has no clue what we consider state in this scenario, and we certainly haven’t made any effort to tell it. It would make the most sense to add our custom history point logic in the quarterbackClicked event handler. The way we did this in our last article was by calling the AddHistoryPoint method on the ScriptManager control. Well instead of using the ScriptManager, we’re going to use the Sys.Application class in the ASP.NET AJAX libraries. It also has a method called addHistoryPoint that serves the exact same purpose as it’s server-side counterpart. Let’s modify the quarterbaclkClicked event handler to include the call to addHistoryPoint:

function quarterbackClicked(e) 
{ 
    var name = e.target.innerHTML; 
    Sys.Application.addHistoryPoint({FavoriteQuarterback: name}, name); 
    selectQuarterback(name); 
}

Notice that instead of passing it two parameters for the key/value pair that represents our state, we’re passing it a JSON object. “FavoriteQuarterback” is our history key, and the value is the name of the selected quarterback. The second parameter represents the browser title associated to this history point.

If I run the app, and then select a list item, I see the following:

lit-2-7-2008-95745-am.png

Great, so we’ve got our list selection and history points working, but now we need to tell the app how to recreate the user’s state upon request. In the last article we used the ScriptManager’s Navigate event, and as you might have already guessed, in this article we’re going to use the Sys.Application class’s navigate event. Let’s modify our pageLoad event to include a handler for the navigate event:

function pageLoad() 
{ 
    quarterbackItems = $get("client-side").getElementsByTagName("li");          
 
    for (var i = 0; i < quarterbackItems.length; i++) 
    { 
        $addHandler(quarterbackItems[i], "click", quarterbackClicked); 
    }          
 
    Sys.Application.add_navigate(function(sender, e) 
                                 { 
                                    selectQuarterback(e.get_state()["FavoriteQuarterback"]); 
                                 }); 
}

The event arguments that is passed into the event handler has a property called “state” that returns back the key/value pair of history points. In this case we’re simply retrieving the FavoriteQuarterback value and sending it to the selectQuarterback method.

So what does our URL look like when using AJAX History from the client-side? If I run the app and select Donnovan McNabb, the URL looks like the following:

http://localhost:49652/Default.aspx#FavoriteQuarterback=Donnovan%20McNabb

Notice that the structure of the URL is identical to what we saw in the last article, with a few exceptions. You may notice that the double ampersand is gone. Like was mentioned previously, the double ampersand is used only to prefix server-side history points, which in this case we don’t have any of.

There is still one minor change that we need to make to our JavaScript code before moving on, and it is related to the main difference between the client and server approaches. When you call the ScriptManager’s AddHistoryPoint method, all it does it modify the current URL, which effectively registers the history point with the browser. The Navigate event doesn’t fire until you use the back or forward buttons, or return from a bookmarked history point. The Sys.Application class’s addHistoryPoint method on the other hand does trigger the navigate event after being called. So what does that mean for our appication? Well, when I add the history point in the quarterbackClicked event handler, we are also then calling the selectQuarterback method. The “problem” is that the call to addHistoryPoint will trigger the navigate event, which in turns calls selectQuarterback. When the user manually selects a list item, selectQuarterback is being called twice, whereas when they navigate between history points (via back/forward buttons or bookmarks), it would only be called once. To fix this, we can just modify the quarterbackClicked method by removing the call to selectQuarterback, since we know our navigate event handler will take care of that for us:

function quarterbackClicked(e) 
{ 
    var name = e.target.innerHTML; 
    Sys.Application.addHistoryPoint({FavoriteQuarterback: name}, name); 
}

Perfect! Now I’ll run the app and select Carson Palmer:

 lit-2-7-2008-13246-pm.png

I then select Drew Brees:

lit-2-7-2008-13602-pm.png

I then select Peyton Manning:

lit-2-7-2008-13708-pm.png

I hit the back button twice, and then hit the forward button once:

lit-2-7-2008-13801-pm.png

Beautiful. Our app works perfectly, and it was written completely using JavaScript and HTML. Hopefully this exercise highlights how easily you could developer very rich and compelling web applications using the ASP.NET AJAX libraries in conjunction with the new AJAX History feature. It is so rediculously easy to add history to an AJAX application that it really opens up the realistic oppurtunities developers have to enhance web applications, whether they’re existing or brand new.

The final scenario of interest is intermingling server-side and client-side history together. Can it be done gracefully? How exactly does it work? Why would I ever use it? In the final part of this series, we’ll examine the migration points between each approach.