Tuesday, September 29, 2009

Increase Your Website Performance by Hosting jQuery with a CDN

In the following screencast I will demonstrate how to speed up your website by using a Content Delivery Network (CDN). Specifically, I will be swamping out a local copy of jQuery with one hosted by Google. You can host a variety of files (example: jQuery, jQuery UI, Prototype, script.aculo.us, MooTools, Dojo, SWFObject, YUI, etc...) with a CDN as well, but the following screencast only shows jQuery being hosted.

First of all, you might be wondering "What is a CDN and why do I need to use one?". If so, you are in luck because Encosia wrote a great blog post concerning this question and here is what he came up with. A CDN provides...

  1. Decreased Latency
  2. Increased Parallelism
  3. Better Caching

For a detailed explanation of the above 3 concept please read his detailed blog post. Now without further ado, here is the screencast.

In the above screencast, I showed how you can replace your local reference of jQuery (see line 4 below) with a version of jQuery that is hosted on a CDN (such as line 5 from Google or line 6 from Microsoft).

<head id="Head1" runat="server">
    <title>Test Page</title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function() {
            console.log('jQuery has been loaded & document is ready!');
        });
    </script>
</head>

It is worth to not that even after updating your update to use Google or Microsoft as your CDN, YSlow will still not recognize those files as being hosted on a CDN. YSlow only recognizes itself, Yahoo, as a known CDN. The good news is that you can register other CDNs (such as Google &| Microsoft) deep inside of Firefox's configuration. In order to update this setting you can follow these instructions…

  1. Type in 'about:config' into the Firefox's navigation TextBox
  2. Filter for the 'extensions.yslow.cdnHostnames' Preference Name
  3. Double-Click & enter 'ajax.googleapis.com,ajax.microsoft.com' into the dialog box
  4. Restart Firefox and re-run YSlow
    As I mentioned above, there are many files on CDNs that are available for you to reference in your project. The two CDNs that I highlighted in the above screencast are…

Quickly Testing Various jQuery UI Themes on Your Website

The following short screencast shows how you can use the jQuery UI ThemeRoller Firefox Bookmarklet to quickly switch the theme on your webpage in order to compare and tweak out the colors that is just right for your website.

 

Not only do the jQuery UI Plugins support the jQuery UI Themes, but there are several other jQuery Plugins that also utilize the themes as well such as

    If I am missing some others, please leave a comment and I will add it to the above list.

Tuesday, September 22, 2009

Jumpstarting Your Next jQuery Plugin with an Online Tool

The following screencast focuses on how to quickly make a jQuery plugin. The intent is not to dig deep into the ins and outs of a jQuery Plugin’s wiring. If that is what you are looking for there are many other good tutorials out there for that such as…

This screencast’s focus is to build off of your current knowledge of how to build a jQuery Plugin (although it doesn’t have to be too deep), and allow you to quickly focus on the building your plugin, rather than worrying about how all the little pieces are wired together.

The tool we will be using is called Starter: jumptstart Your jQuery Plugins and you just provide the new jQuery Plugin name, optional namespace, parameters, options, etc… and then you are on your way focusing on the guts of your Plugin.

 

Update: This screencast has been posted on Nettuts+ for voting. If you like it, then please consider voting for the 3rd entry on the Nettuts+ blog post…

The plugin that we will be creating is an ImageTextOverlay that will allow you to provide a list of message and overlay them over a message. The message will fade in and out in succession and you will be able to change the properties of each message (such as it’s location, size, color, etc…). I was inspired to write this small plugin after hearing someone on Twitter wanting something similar to this.

Sometimes it is easiest if we look at how we want to use our Plugin before actually creating it. So, here is a simple page that is selecting an image and calling our imageTextOverlay plugin. You can see how there is a default top & left positions provided and then a list of messages. Each message only needs to have a text property provided, but you can also provide many other properties to override the default values.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="jquery.imagetextoverlay.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function() {
            $('#ctlImage').imageTextOverlay({
                top: "10px",
                left: "10px",
                messages: [{
                        text: "Message 1"
                    }, {
                        text: "Message 2",
                        top: "50px",
                        left: "50px",
                        fontSize: "22px"
                    }, {
                        text: "Message 3",
                        top: "100px",
                        left: "100px",
                        color: "black",
                        fontSize: "48px",
                        backgroundColor: "#CCCCCC"
                    }, {
                        text: "Message 4",
                        top: "200px",
                        left: "200px",
                        letterSpacing: "-1px",
                        color: "red",
                        fontSize: "24px",
                        backgroundColor: "white"
                    }
                ]
            });
        });    
    </script>
</head>
<body>
    <img id="ctlImage" src="curtains.jpg" />
</body>
</html>

The next step is to starting entering our plugin Class Name and Default Options into the Starter: jumptstart Your jQuery Plugins online tool. Then we just click the Create button to prototype out our plugin! We can either copy/paste the results into our own file or there is even a Download button so you don’t have to copy/paste :)

StarterInput

Now we can focus on writing the core logic of our jQuery plugin and not have to worry about all the nuts and bolts of how a plugin should be structured. So, here is what I put together for the ImageTextOverlay plugin. I will highlight only the lines of code that I actually wrote… everything else was generated by the online tool!

(function($){
    
    $.ImageTextOverlay = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;
        
        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el; 
        
        // Add a reverse reference to the DOM object
        base.$el.data("ImageTextOverlay", base);
        
        base.init = function(){
            
            base.options = $.extend({},$.ImageTextOverlay.defaultOptions, options);
            
            // Put your initialization code here
            base.createAndUpdateImageText(base.$el, base.options);
        }
        
        // Sample Function, Uncomment to use
        // base.functionName = function(paramaters){
        //     
        // }

        base.createAndUpdateImageText = function($ctlImage, options) {
            var $ctlText = base.createImageText();
            base.updateImageText($ctlImage, $ctlText, options, function() {
               base.createAndUpdateImageText($ctlImage, options);
            });
        }        
        
        base.createImageText = function() {
            var $imageText = $('#ctlImageText');

            if ($imageText.length == 0) {
                $('<div id="ctlImageText" />')
                    .css({
                        position: "absolute"
                    })
                    .appendTo('body')
                    .hide();
                $imageText = $('#ctlImageText');
            }

            return $imageText;
        }    

        base.messageIndex = 0;
        base.updateImageText = function($ctlImage, $ctlText, options, onComplete) {
            var message = options.messages[base.messageIndex++ % options.messages.length];
            var messageOptions = $.extend({}, options, message);
            $ctlText.html(message.text).css({
                fontSize: messageOptions.fontSize
            });
            
            $ctlText.css({
                top: messageOptions.top,
                left: messageOptions.left,
                color: messageOptions.color,
                letterSpacing: messageOptions.letterSpacing,
                backgroundColor: messageOptions.backgroundColor,
            }).fadeIn('slow').animate({ opacity: 1.0 }, 3000).fadeOut('slow', function() {
                onComplete();
            });
        }
        
        base.init();
    }
    
    $.ImageTextOverlay.defaultOptions = {
        fontSize: "24px",
        letterSpacing: "normal",
        color: "white",
        backgroundColor: "transparent"
    }

    $.fn.imageTextOverlay = function(options){
        return this.each(function(){
            (new $.ImageTextOverlay(this, options));
        });
    }

    // This function breaks the chain, but returns
    // the ImageTextOverlay if it has been attached to the object.
    $.fn.getImageTextOverlay = function(){
        return this.data("ImageTextOverlay");
    }
    
})(jQuery);

As I mentioned above, I only wrote the lines that are highlighted. The rest of the plugin was written by the Starter: jumptstart Your jQuery Plugins online tool!

If you are interested in other screencasts, I have made several others that you may be interested in as well…

Monday, September 21, 2009

Unit Testing with jQuery using FireUnit & QUnit

Today’s screencast is the 5th in a series of developer Firefox Extensions. You can view my previous 3 short Screenr screencasts here…

    In addition to this post being part in a series of Firefox Extension screencasts, it is actually also the 3rd part of an old series looking through various JavaScript Unit Testing frameworks…
    The following short screencast will give a quick review of the FireUnit Firefox Firebug Add-on and also the QUnit Unit Testing framework for jQuery. In case you don’t want to watch the 4 minute screencast I thought I would go ahead and flush out the rest of this blog post with code, screenshots, and commentary.
      As a review, to exercise our Unit Testing frameworks we have been using a simple Pig Latin function as our testing subject.

    This code is not optimal and it will be refactored in a future post. So, please focus on the Unit Testing and not the actual Pig Latin function :)

    So, here is the Pig Latin converter function we will be using for our tests…

    function EnglishToPigLatin() {
        this.CONSONANTS = 'bcdfghjklmnpqrstvwxyz';
        this.VOWELS = 'aeiou';
        this.Translate = function(english, splitType) {
            var translated = '';    
            
            var words = english.split(/\s+/);
            for (var i = 0; i < words.length; ++i) {
                translated += this.TranslateWord(words[i]);
                if (i+1 < words.length) translated += ' ';
            }
            
            return translated;
        }
        this.TranslateWord = function(english) {
           /*const*/ var SYLLABLE = 'ay';
    
           var pigLatin = '';
              
           if (english != null && english.length > 0 && 
              (this.VOWELS.indexOf(english[0].toLowerCase()) > -1 || this.CONSONANTS.indexOf(english[0].toLowerCase()) > -1 )) {
              if (this.VOWELS.indexOf(english[0].toLowerCase()) > -1) {
                 pigLatin = english + SYLLABLE;
              } else {      
                 var preConsonants = '';
                 for (var i = 0; i < english.length; ++i) {
                    if (this.CONSONANTS.indexOf(english[i].toLowerCase()) > -1) {
                       preConsonants += english[i];
                       if (preConsonants.toLowerCase() == 'q' && i+1 < english.length && english[i+1].toLowerCase() == 'u') {
                          preConsonants += 'u';
                          i += 2;
                          break;
                       }
                    } else {
                       break;
                    }
                 }
                 pigLatin = english.substring(i) + preConsonants + SYLLABLE;
              }
           }
           
           return pigLatin;    
        }
    } 

    First we are going to write a simple set of 20 FireUnit tests that can be ran inside Firefox’s Firebug using the FireUnit Add-on.

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="PigLatinBad.js"></script>
        <script type="text/javascript">
            var englishToPigLatin = new EnglishToPigLatin();
    
            //Invalid Arguments
            fireunit.compare(englishToPigLatin.TranslateWord(null), '', 'Passing Null Should Return Blank');
            fireunit.compare(englishToPigLatin.TranslateWord(''), '', 'Passing Blank Should Return Blank');
            fireunit.compare(englishToPigLatin.TranslateWord('1234567890'), '', 'Passing 1234567890 Should Return Blank');
            fireunit.compare(englishToPigLatin.TranslateWord('~!@#$%^&*()_+'), '', 'Passing ~!@#$%^&*()_+ Should Return Blank');
    
            //Consonant Words
            fireunit.compare(englishToPigLatin.TranslateWord('beast'), 'eastbay', 'Passing Beast Should Return Eastbay');
            fireunit.compare(englishToPigLatin.TranslateWord('dough'), 'oughday', 'Passing Dough Should Return Oughday');
            fireunit.compare(englishToPigLatin.TranslateWord('happy'), 'appyhay', 'Passing happy Should Return appyhay');
            fireunit.compare(englishToPigLatin.TranslateWord('question'), 'estionquay', 'Passing question Should Return estionquay');
            fireunit.compare(englishToPigLatin.TranslateWord('star'), 'arstay', 'Passing star Should Return arstay');
            fireunit.compare(englishToPigLatin.TranslateWord('three'), 'eethray', 'Passing three Should Return eethray');
    
            //Vowel Words
            fireunit.compare(englishToPigLatin.TranslateWord('apple'), 'appleay', 'apple Should Return appleay');
            fireunit.compare(englishToPigLatin.TranslateWord('elijah'), 'elijahay', 'elijah Should Return elijahay');
            fireunit.compare(englishToPigLatin.TranslateWord('igloo'), 'iglooay', 'igloo Should Return iglooay');
            fireunit.compare(englishToPigLatin.TranslateWord('octopus'), 'octopusay', 'octopus Should Return octopusay');
            fireunit.compare(englishToPigLatin.TranslateWord('umbrella'), 'umbrellaay', 'umbrella Should Return umbrellaay');
    
            //Sentences
            fireunit.compare(englishToPigLatin.Translate('hello'), 'ellohay', "Passing 'hello' Should Return 'elloh'");
            fireunit.compare(englishToPigLatin.Translate('hello world'), 'ellohay orldway', "Passing 'hello world' Should Return 'elloh orldw'");
            fireunit.compare(englishToPigLatin.Translate('hello world!'), 'ellohay orld!way', "Passing 'hello world!' Should Return 'ellow orld!w'");
            fireunit.compare(englishToPigLatin.Translate('Hello World'), 'elloHay orldWay', "Passing 'Hello World' Should Return 'elloH orldW'");
            fireunit.compare(englishToPigLatin.Translate('Hello World!'), 'elloHay orld!Way', "Passing 'Hello World!' Should Return 'elloH orld!W'");
    
            // Wait for asynchronous operation.
            setTimeout(function() {
                // Finish test
                fireunit.testDone();
            }, 1000);
        </script>
    </head>
    <body />
    </html>

    If we run the webpage inside of Firefox, we don’t see anything from the browser window, but if we open Firebug and click the “Tests” tab, then we can see the output of the 20 tests.

    FireUnit

    One of the other nice features of FireUnit is that its compare assertion will actually show the difference of the two values instead of just saying they are the same or not. Here is an example of the output from a failing compare…

    FireUnitCompare

    The output is pretty impressive, but what if you already have a lot of existing QUnit Unit Tests or what if you would also like to have some sort of User Interface to your test page. Well, the nice thing about FireUnit is that you can integrate it into QUnit! By adding several lines of code we can have the output of our QUnit tests render to the FireUnit Add-on as well!

    The following is a set of QUnit Unit Tests with 4 lines of code near the end that registers the output with FireUnit as well.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
        <title>English To Pig Latin QUnit Tests</title>
        <link rel="stylesheet" href="http://jqueryjs.googlecode.com/svn/trunk/qunit/testsuite.css" type="text/css" media="screen" />
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script type="text/javascript" src="http://jqueryjs.googlecode.com/svn/trunk/qunit/testrunner.js"></script>
        <script type="text/javascript" src="PigLatinBad.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
    
                module("Pig Latin");
    
                var englishToPigLatin = new EnglishToPigLatin();
    
                test('Invalid Arguments', function() {
                    equals(englishToPigLatin.TranslateWord(null), '', 'Passing Null Should Return Blank');
                    equals(englishToPigLatin.TranslateWord(''), '', 'Passing Blank Should Return Blank');
                    equals(englishToPigLatin.TranslateWord('1234567890'), '', 'Passing 1234567890 Should Return Blank');
                    equals(englishToPigLatin.TranslateWord('~!@#$%^&*()_+'), '', 'Passing ~!@#$%^&*()_+ Should Return Blank');
                });
    
                test('Consonant Words', function() {
                    equals(englishToPigLatin.TranslateWord('beast'), 'eastbay', 'Passing Beast Should Return Eastbay');
                    equals(englishToPigLatin.TranslateWord('dough'), 'oughday', 'Passing Dough Should Return Oughday');
                    equals(englishToPigLatin.TranslateWord('happy'), 'appyhay', 'Passing happy Should Return appyhay');
                    equals(englishToPigLatin.TranslateWord('question'), 'estionquay', 'Passing question Should Return estionquay');
                    equals(englishToPigLatin.TranslateWord('star'), 'arstay', 'Passing star Should Return arstay');
                    equals(englishToPigLatin.TranslateWord('three'), 'eethray', 'Passing three Should Return eethray');
                });
    
                test('Vowel Words', function() {
                    equals(englishToPigLatin.TranslateWord('apple'), 'appleay', 'apple Should Return appleay');
                    equals(englishToPigLatin.TranslateWord('elijah'), 'elijahay', 'elijah Should Return elijahay');
                    equals(englishToPigLatin.TranslateWord('igloo'), 'iglooay', 'igloo Should Return iglooay');
                    equals(englishToPigLatin.TranslateWord('octopus'), 'octopusay', 'octopus Should Return octopusay');
                    equals(englishToPigLatin.TranslateWord('umbrella'), 'umbrellaay', 'umbrella Should Return umbrellaay');
                });
    
                test('Sentences', function() {
                    equals(englishToPigLatin.Translate('hello'), 'ellohay', "Passing 'hello' Should Return 'elloh'");
                    equals(englishToPigLatin.Translate('hello world'), 'ellohay orldway', "Passing 'hello world' Should Return 'elloh orldw'");
                    equals(englishToPigLatin.Translate('hello world!'), 'ellohay orld!way', "Passing 'hello world!' Should Return 'ellow orld!w'");
                    equals(englishToPigLatin.Translate('Hello World'), 'elloHay orldWay', "Passing 'Hello World' Should Return 'elloH orldW'");
                    equals(englishToPigLatin.Translate('Hello World!'), 'elloHay orld!Way', "Passing 'Hello World!' Should Return 'elloH orld!W'");
                });
    
                if (typeof fireunit === "object") {
                    QUnit.log = fireunit.ok;
                    QUnit.done = fireunit.testDone;
                }
    
            });
        </script>
    </head>
    <body>
        <h1>English To Pig Latin QUnit Tests</h1>
        <h2 id="banner"></h2>
        <h2 id="userAgent"></h2>
        <ol id="tests"></ol>
        <div id="main"></div>
    </body>
    </html>
    
    QUnitWithFireUnit 

    Now, not only do we have a User Interface on the webpage, but we also have the tests running in Firebug.

    For more information about FireUnit you can check out a post by Jonn Resig and it’s Wiki on GitHub. And if you are interested in QUnit, there is a nice overview on the jQuery webiste.

    Sunday, September 20, 2009

    Using StructureMap with ASP.NET MVC & MVC Contrib

    I’ve found myself using the MVC Contrib project more and more lately. There are tons of golden framework nuggets just waiting to be used.

    I recently integrated StructureMap into the my current ASP.NET MVC framework using MVC Contrib. The reason I decided to write this post is because most of the resources I found on the internet appeared to be a little out of date and used deprecated StructureMap APIs. So, here it goes…

    Note: The following examples are using StructureMap v2.5.3 & ASP.NET MVC v2 Preview 1 & MVC Contrib MVC2 Branch code bits. You may find minor differences in API &| syntax if you are using a different version.

    First lets investigate why StructureMap is necessary in the first place. You can find some good blog posts by Jeremy D. Miller about the basics of the Dependency Injection Pattern and using an IOC tool.

    In order to facilitate mocking and decouple our application we pass an interface of our service into our controller instead of a concrete class. The default controller factory that ASP.NET MVC uses requires a default constructor to be present, but we are going to define our own Controller Factory later in this post using one of the MVC Contrib classes.

    Note: There is actually a really good screencast with @robconery and @jeremydmiller about using StructureMap in ASP.NET MVC. There were several “Aha!” moments for me as I watched it. The StructureMap API has changed slightly since the screencast, but I will show the updated syntax in the following of this post.

    The following is a typical ContactController class that will house the Index, Details, Create, Edit, and Delete actions. You will notice that instead of having a default constructor, I have an overloaded contructor and am passing in an interface to my service. I will wire up StructureMap to handle passing in the appropriate object later in this post.

    public partial class ContactController : Controller
    {
        private IContactService service;
    
        public ContactController(IContactService service)
        {
            this.service = service;
        }
    }    

    The wiring part, happens typically in the Application_Start event from the Global.asax.cs file. In addition to Registering your MVC routes (which should have already been wired up when you created your MVC application) you need to both configure StuctureMap to know what concrete classes map to what interfaces as well as tell MVC to use StructureMap to create its controllers.

    public class Global : HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes(RouteTable.Routes);
    
            Bootstrapper.ConfigureStructureMap();
            ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
        }
    }

    I am going to attempt and explain the above code snippet line by line, so lets start with the Bootstrapper.ConfigureStructureMap() and then we will discuss the StructureMapControllerFactory().

    After everything is said and done, the important part of StructureMap is that it knows what interfaces should map to what concrete types so that it can inject the appropriate instances at runtime. This is where the Bootstrapper.ConfigureStructureMap() comes into play.

    public static class Bootstrapper 
    {
        public static void ConfigureStructureMap()
        {
            ObjectFactory.Initialize(x => x.AddRegistry(new MyApplicationRegistry()));            
        }
    }
    
    public class MyApplicationRegistry : Registry
    {
        public MyApplicationRegistry()
        {
            Scan(assemblyScanner =>
            {
                assemblyScanner.TheCallingAssembly();
                assemblyScanner.WithDefaultConventions();
            });
        }
    }

    The above code is initializing StructureMap with the MyApplicationRegistry that contains the rules for the interface & concrete type mappings. You may be wondering, “But I don’t see where IContactService is mapped to ContactService” and that is a very good question. The answer is that StuctureMap takes the Convention Over Configuration approach and tries to take some educational guesses based on a set of default naming conventions.

    Lets say that your configuration isn’t following standard naming conventions. Can you still use StructureMap? Well, of course you can :) You have full control over the mappings and can set them up however you wish. The following is an example of me manually doing the mapping instead of using the default naming conventions. The Bootstrapper remains the same, so I only will show the code that is different below…

    public class MyApplicationRegistry : Registry
    {
        public MyApplicationRegistry()
        {
            ForRequestedType<IContactService>().TheDefaultIsConcreteType<ContactService>();
            ForRequestedType<IValidationRunner>().TheDefaultIsConcreteType<ValidationRunner>();
        }
    }

    Now lets focus on the StructureMapControllerFactory that we saw after we Configured StructureMap from the Global.asax. The StructureMapControllerFactory class that I am instantiating actually comes with the MVC Contrib project.  The contents of this class isn’t really all that complicated, but its one less thing you have to write by hand. The following is an example of a oversimplified implementation of the StructureMapControllerFactory that you could write yourself…

    public class StructureMapControllerFactory : DefaultControllerFactory
    {
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return ObjectFactory.GetInstance(controllerType) as IController;
        }
    }

    Since we separated our dependencies and used StructureMap for injection our application is now loosely coupled and our ability to Unit Test more areas has increased.

    Stay tuned for a new series where I will upgrade a standard ASP.NET MVC project to ASP.NET MVC 2 and then integrate StructureMap, Moq, MbUnit, and suite of Unit Tests.

    Friday, September 18, 2009

    ASP.NET AJAX Add-ons (FireAtlas & FireCookie) for Firefox's Firebug

    Today’s screencast is the 4th in a series of developer Firefox Extensions. You can view my previous 3 short Screenr screencasts here…

    For those of you that do ASP.NET or ASP.NET AJAX development, then the following Firebug Add-ons might be of interest to you.

    FireAtlas is a tool that enables you to view the PageRequestManager events, trace WebService calls, inspect Partial Updates, and view any installed application components. You can actually try out some samples pages to exercise most of the functionality of this Add-on, but I will be viewing the twitter scheduler application TwtMstr (developed by @wbm) to demonstrate some of the features in my screencast.

    FireCookie is another useful tool that allows you to view any cookies that are relevant for the current web page. This can be handy for an ASP.NET developer to inspect the .ASPXROLES, .ASPXAUTH, or ASP.NET_SessionId values that are common for most ASP.NET applications.

     

    Yet again, I hope this was beneficial to you. If you enjoyed the presentation I would appreciate either a comment to this blog &| a tweet about it to share with others.

    "#ASPNET #AJAX Add-ons (FireAtlas & FireCookie) for #Firefox's #Firebug" by @elijahmanor #tech #nettuts #screencast http://j.mp/111ZQO

    Also, if you have any suggestions that you have to help become a better presenter I would appreciate that as well. If you have a minute, please add a comment with your thoughts.

    Thursday, September 17, 2009

    Reasons Why .NET Developers Love Their MacBook Pros

    Initial Questionnaire

    I recently posted an informal survey asking .NET Developers why they love their MacBook Pros and I want to thanks the 51 individuals who responded to my survey.

    Objective Results

    The first four questions (other than name, twitter, etc…) were general questions about their MacBook Pro hardware. Those types of questions are easy and quick to graph.

    Note: If you see some discrepancies of the numbers please note that shortly after I first submitted the questionnaire I added the hardware questions. So, the first several people who answered the survey didn’t have those questions.

    Reasons You Love your MacBook Pro for .NET Development

    As to summarize the above charts, it seems that most of the people who responded to the survey were .NET developers using a MacBook Pro with a 2.66MHz Processor, 4 GB RAM, and a 15 inch monitor.

    Subjective Results

    Well, objectively that is all I can really graph. The rest of the questions allowed free form text, which is difficult to chart :) however, I did attempt to summarize each question into common answers so that I can graph them. So, here are my findings…

    WhyDidSwitchFromPcToMac

    So it seems that the majority of those that switched did so because they had the opportunity to run both OSX and Windows, they felt the hardware was better (faster & quality), and they thought it was more stylish :)

    WouldYouConsiderMovingBackToPc

    Of those that have switched from a PC to a Mac the vast majority (64%) said that they would not switch back to the PC and only a handful were adamant about moving back to the PC.

    AreThereFeaturesThatTheMacHasThatThePcDoesnt

    Mac users feel that their OS is more usable and simple compared to Windows, they feel the software for OSX is better, is more stable, and it was mentioned over and over that the multitouch trackpad on the Mac is a plus!

    DoYouFindYouAreSacrificingPerformanceByUsingTheMac

    An overwhelming majority of Mac users feel that they are no sacrificing any performance by using the Mac. Of those that did feel they were lacking some performance, they attibuted it to using a VM (VMWare or Parallels) and recommending using Bootcamp instead.

    AnythingElseIShouldKnowBeforeIChange

    As a last ditch effort to glean any useful information, I asked if there was anything else I needed to know before I made the change to a Mac. A large portion of the responses encouraged me to purchase VM software (VMWare or Parrallels), reprogram my keyboard for the PC, and to buy as much of RAM as possible.

    Conclusion

    Overall, I am very pleased with the responses of the questionnaire. I am even more inclined to make the switch myself. Only time will tell if this will actually take place, but I do appreciate you humoring me in this research and I’m sure you will know when and/or if I do take the Mac plunge for .NET development :)

    Wednesday, September 16, 2009

    Page Speed & YSlow Firebug Extensions to Increase Web Page Performance

    Today’s screencast is the 3rd in a series of developer Firefox Extensions. You can view my previous 2 short Screenr screencasts here…

    You will most likely be asked to speed up the performance of some web page whether it be your corporate, personal, or some other web page. There are so many things that can cause a web page to be perceived as slow that it is helpful to have a tool to give you a guideline of where to start. 

    Fortunately, there are two great tools for the Firebug Add-on for Firefox that do performance checking of any given web page. The tools we will be looking at in the following screencast are Google’s Page Speed and Yahoo’s YSlow Add-ons.

     

    Yet again, I hope this was beneficial to you. If you enjoyed the presentation I would appreciate either a comment to this blog &| a tweet about it to share with others.

    "Page Speed & YSlow Firebug Extensions 2 Increase Web Page Performance" by @elijahmanor #tech #nettuts #webdev #screencast http://j.mp/7IFWJ

    Also, if you have any suggestions that you have to help become a better presenter I would appreciate that as well. If you have a minute, please add a comment with your thoughts.

    Tuesday, September 15, 2009

    Digging Into The FireQuery Add-on for jQuery

    Yesterday I posted my first short Screenr screencast

    Today I decided to record another screencast, and I decided to dig into the FireQuery add-on for Firebug.

    FireQuery adds extra functionality to the HTML tab and allows you to visually see embedded data elements and event handlers that were added via jQuery. Also, the familiar jQuerify Bookmarklet has been built into Firebug allowing you to inject jQuery into pages that didn’t have it installed previously. This enables you to play around with jQuery or extract information for a webpage that might not previously have jQuery installed.

     

    Yet again, I hope this was beneficial to you. If you enjoyed the presentation I would appreciate either a comment to this blog &| a tweet about it to share with others.

    "Digging into the FireQuery Add-on for jQuery" by @elijahmanor #tech #nettuts #jquery #screencast http://j.mp/1T9RKE

    Also, if you have any suggestions that you have to help become a better presenter I would appreciate that as well. If you have a minute, please add a comment with your thoughts.

    Monday, September 14, 2009

    Firefinder for Firebug for Firefox for Fiddling with jQuery

    Tonight I created my first Screenr screencast showcasing the Firefinder Add-on for the popular Firebug Add-on for the even more popular Firefox browser :) Whew, that was a mouth full!

    Firefinder is a helpful tool when creating a selector for jQuery, which is usually where you start for most jQuery work. In the following screencast I show how to use Firefinder in conjunction with the Firebug console window in order to add some animation effects to my blog on the mouse over and mouse out events.

     

    I hope you found this screencast helpful. There are many Firebug Add-ons that are useful for web development and I hope to extend this series to include several of the others.

    If you enjoyed the above screencast I would appreciate it if you could retweet it by clicking the following and posted it to your Twitter account… thanks :)

    "Firefinder for Firebug for Firefox for Fiddling with jQuery" by @elijahmanor #tech #nettuts #jquery #screencast http://j.mp/ZKtTT

    Maintain Scroll Position On Page Refresh Using ASP.NET or jQuery

    There is a feature of ASP.NET that isn't widely known called MaintainScrollPositionOnPostback, which is a common way of maintaining the scroll position after a Postback. Behind the scenes ASP.NET passes a hidden variable with the page location and resets it with JavaScript after the page re-renders.

    <%@ Page 
       Title="Page Title Here" 
       MaintainScrollPositionOnPostback="true" 
       Language="C#" 
       MasterPageFile="~/YourMasterPage.master" 
       AutoEventWireup="true" 
       CodeBehind="YourCodeBehind.aspx.cs" 
       Inherits="YourCodeBehind" %>

    However, this method will not work if the Postback does a Redirect on the server.

    If the Postback does a Redirect instead of re-rendering the same page, then you could use the ScrollSaver jQuery script. All you have to do is include the script on the page and before a Postback occurs it will save the location of each element in a cookie and then restore it when the page re-renders. This will work for both a Postback and a Redirect.

    All you have to do is include the jQuery plugin into your page. You don’t have to actually call any jQuery methods… it just does everything for you!

    <script type="text/javascript" src="scrollsaver.min.js"></script>

    I would recommend only adding this script to the page you are interested in maintaining position in order to minimize any risk of affecting other pages in your project. The overhead of the minimized plugin is only 1.63K and when you consider it will get cached on the client that is pretty good :)

    Thursday, September 10, 2009

    ASP.NET MVC 1.0 TDD Book Review

    AspNetMvcTdd I recently finished reading Emad Ibrahim’s ASP.NET MVC 1.0 Test Driven Development book and I thought I would do a detailed review and share my thoughts and findings.
    Before I get into the details of the book, it is important to know that the audience of this book is not for novice programmers or experience non ASP.NET developers. To really get value from this book, you should have some decent exposure to ASP.NET under your belt.
    With that said, this book is a very good overview of both ASP.NET MVC and Test Driven Development (TDD). It takes the reader through the process of developing a whole application using the Test First methodology. I found this interesting in that some decisions Emad made initially were later refactored in the book as the application evolved and changed, which is a great way to see the value of TDD and its approach.
    This book covers quite a few advanced programming concepts that may be new to you such as various Design Patterns (Strategy, Null Objects, Repository, etc…), Design Principles (Open-Closed Principle, YAGNI, DRY, Inversion of Control, Single Responsibility, Convention Over Configuration, etc…). Emad does a good job about explaining these concepts as he approaches them in the application.
    About the same time that I was reading this book, I was in the process of evaluating various tools and frameworks to use for a new ASP.NET MVC v2 project I am working on. I found it interesting that Emad ended up choosing most of the same tools that I had at the time such as: MbUnit, Ninject, Moq, and jQuery. If you are familiar with tools other than the ones he chose at the time of writing this book, you should be able to easily substitute your favorite tool instead. Most of the competitors for these tools have basically the same features.
    Since this is a new book, I did run across numerous typos, references to code that wasn’t displayed, refactored code that wasn’t indicated in the text, and several other minor issues, but all in all I knew what Emad was getting at and it wasn’t hard to follow his train of thought. I submitted these inconsistencies to the Errata to hopefully clean up these small issues for future printings of this book. I posted my findings and you can review them online.
    I highly recommend downloading the source code from this book (which you can do for free). It is one of the few projects that I’ve seen that has a plethora of Unit Tests to look at and get an idea of how to test your ASP.NET MVC project. I’ve seen numerous other ASP.NET MVC projects that only have a minimal number of Unit Tests and don’t really give you a good idea of how you could get good Code Coverage.
    If you are interested in getting a jumpstart into both ASP.NET MVC and Test Driven Development, then I think this is a great book for you to get. However, if you aren’t so sure about TDD and you just want to get up to speed on ASP.NET MVC, then I might recommend you get one of the other beginning ASP.NET MVC books such as:
      Note: A danger of listing books is that I may have missed one ;) If so, please leave a comment listing any of another ASP.NET MVC book published as of the date of this blog post and I will be happy to add it to the list.
    I haven’t read any of the above books yet, but I do hope to in the near future and as I do I plan to perform book reviews for those as well.
    Thank you Emad for all of your hard work on your book. I enjoyed reading it over my extended Labor Day weekend :)
    Updated: You can view the Errata document I put together listing all the inconsistencies, typos, minor issues, etc… online.

    Wednesday, September 09, 2009

    Recursively Unblock Assemblies with Streams

    MvcContribEver since my recent blog post Unblocking Assembly Due to AspNetHostingPermission Security Exception I have been pretty careful about unblocking Assemblies after downloading them from the internet.

    However, today I decided to download the MVCContrib.Extras.release.zip which has over 100 assemblies, pdbs, and xml files of which ALL are blocked by Windows 7!

    Since there is no way to multi-select and unblock the files at once, I shuttered at the thought of right-clicking each file and unblocking them one by one. There has to be a better way… and to my fortune there is :)

    The answer is yet another useful too from Sysinternals called Streams.

    Streams is a command line tool that lets you unblock one or more files at a time and you can even recursively perform unblocks! Yippee

    Immediately I started to look for a feature to right-click folder option to open a command prompt at that location (like I used to with the Open Command Window Here Microsoft Power Tool for Windows XP).

    ShiftRightClick

    I didn’t see an Open Command Window Here context menu for Windows 7 when I initially right-clicked on a folder, so I decided to do some quick research to see what is the best way to do this in Windows 7.

    I was pleased to find that the feature is native in Windows 7, but I had just missed it.

    It turns out that if you Shift-Right-Click on a folder then an "Open Command Window Here” context menu will appear! Apparently, this was a feature of Windows Vista too, but as I mentioned in a previous post… I upgraded immediately from Windows XP to Windows 7.

    So, (after downloading Streams and registering it in my System Path Variable) I quickly typed in the following command to save the day.

    streams –s *.*

    Using Streams

    Usage: streams [-s] [-d] <file or directory>

    -s
    Recurse subdirectories.

    -d
    Delete streams.
    Streams takes wildcards e.g. 'streams *.txt'.

     

    Anyway, I didn’t know about either the Streams command line too or the Shift-Right-Click “Open command window here” feature of Windows 7 and thought I would share them with you. Hopefully, they help someone ;) If not, it will help me remember them in the future. 

    Wednesday, September 02, 2009

    Migrated from dasBlog to BlogEngine.NET

    images Well, I just migrated from dasBlog to BlogEngine.NET and I am pleased with the results.

    Initially I just wanted a fresher looking blog theme for dasBlog, but then as I looked more into BlogEngine.NET I was impressed with the features and out-of-box support.

    There are still some some migration issues that I need to address since I am trying to maintain URLs from my old Blogger and dasBlog blogs. I am trying not to abandon those that have bookmarks or try to access my site from a search engine.

    benlogo80 Hopefully all the links you click on from Google, Bing, or where-have-you still work. If you find a link that isn’t redirected to the correct location, PLEASE let me know and I will try to address it.

    Also, if you see any blog post on this site that looks a little off please let me know. I am still ironing out several HTML, JavaScript, and CSS issues from the migration from dasBlog.

    All in all, I am very pleased with the new Blog engine. I plan to keep this one for a while :) However, I reserve the right to manipulate with this theme some.

    Hopefully, your RSS feed still works. At worst, it may seem that my older posts are new, but from here on out it should go back to normal. Thanks for your patience!

    For those that are interested, two great resources that I used to help me get migrated were…

    1. Converted from dasBlog to BlogEngine.NET
    2. Migrated from dasBlog to BlogEngine.NET

    The most important tool I used was the dasBlog to BlogML converter that enabled me to utilize BlogEngine.NET’s import feature.

    Tuesday, September 01, 2009

    DXperience ASP.NET Subscription Giveaway

    DevExpressWell, its time for another great giveaway. This time the great people at Devexpress have offered one of their premier products worth $799.99!

    For this giveaway, you have a chance to win one license of DXperience ASP.NET Subscription with over 20+ ASP.NET controls. In addition, you’ll get updates and support too for a full year!

    Giveaway Rules

    The contest will start today, September 2nd, 2009, and last 7 days concluding on September 8th, 2009 11:59PM. At that point I will pick the winner and announce the results on the following day.

    In order to signup for the giveaway you need to do 3 things…

    1. Follow @elijahmanor on Twitter
    2. Tweet the following…
    3. Add a comment to this blog including your Twitter username

    At the end of the contest I will pick a random comment from this blog entry and then make sure the comment author tweeted the above RT. At that point I will Direct Message the winner (which is why you need to follow @elijahmanor) with further instructions to receive the DXperience ASP.NET Subscription.

    Note: Unlike my last giveaway, I decided that you can add multiple comments to this blog post, but only one per day per person. Multiple comments from the same person in one day is kind, but will not help you win and could just disqualify you from the contest. So please, come by once a day during the contest and leave a comment below. This increases you chances of winning.

    More About the DXperience ASP.NET Subscription

    Want to learn more about the awesome prize? I highly recommend you check out the following:

    1. The DevExpress Online Demos are the quickest way to play with the ASP.NET controls that you might win

    2. Download the fully-functioning trial and test drive the controls locally in your Visual Studio

    3. Check out their blogs, they've got some great content up there

    4. DevExpress has a big developer fan base and their Facebook Page shows this enthusiasm and excitement. Become a fan by going to this page

    Winner Announced…

    Congratulations to Matt Lacey for winning the DXperience ASP.NET Subscription giveaway! Someone from DevExpress will be contacting you shortly with instructions. Thank you for everyone who participated in the contest. I hope to have other giveaways in the future. Stay tuned ;)