Archive

Archive for the ‘CSharp’ Category

Tracking WCF Operations Execution Time

July 13, 2012 5 comments

We all at some point need to measure the performance of the code either because there is something that’s making the process take too long to execute or we just want to know what’s going on and at what rate our service gets hit daily. Tracking method calls and measuring code execution times can be achieved using different ways but I’d like to present a more elegant approach taking advantage of the extensibility options WCF exposes.

IOperationInvoker

This IOperationInvoker interface will be our main point of entry from where we can do all we want. It provides contract for classes that implement it to be used in the WCF execution pipeline to invoke operations. Since my goal is to track the execution time of the operation itself I create nothing but a wrapper around the default OperationInvoker class and I inject code that does the tracking. There is a method that is used for synchronous invocation and two other that handle the asynchronous calls. I will inject code only for synchronous calls but you are free to do it for the asynchronous too. For measuring execution time you should always use the Stopwatch class as it is more accurate than DateTime and TimeSpan because I have seen a lot of people using the latter not knowing that in the end their measurements might be wrong. Here is a sample implementation of IOperationInvoker:

public class TrackingOperationInvoker : IOperationInvoker
{
    private IOperationInvoker _defaultOperationInvoker;
    internal EventHandler<TrackingEventArgs> OnInvokeEnded;

    public TrackingOperationInvoker(IOperationInvoker operationInvoker)
    {
        _defaultOperationInvoker = operationInvoker;
    }

    public bool IsSynchronous
    {
        get { return _defaultOperationInvoker.IsSynchronous; }
    }

    public object[] AllocateInputs()
    {
        return _defaultOperationInvoker.AllocateInputs();
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        Stopwatch stopwatch = null;
        try
        {
            stopwatch = Stopwatch.StartNew();
            return _defaultOperationInvoker.Invoke(instance, inputs, out outputs);
        }
        finally
        {
            RaiseInvokeEnded(stopwatch.ElapsedMilliseconds);
        }
    }

    public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
    {
        return _defaultOperationInvoker.InvokeBegin(instance, inputs, callback, state);
    }

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
    {
        return _defaultOperationInvoker.InvokeEnd(instance, out outputs, result);
    }

    private void RaiseInvokeEnded(decimal elapsedMilliseconds)
    {
        if (OnInvokeEnded != null)
        {
            OnInvokeEnded(this, new TrackingEventArgs(elapsedMilliseconds));
        }
    }
}

I have created a simple EventArgs class that holds the ellapsed time information and the consumer of the invoker is responsible for handling the InvokeEnded event and do whatever makes sense with that information.

public class TrackingEventArgs : EventArgs
{
    public TrackingEventArgs(decimal elapsedMilliseconds)
    {
        ElapsedMilliseconds = elapsedMilliseconds;
    }

    public decimal ElapsedMilliseconds { get; private set; }
}

IOperationBehavior

The IOperationBehavior interface can be used to provide some additional behavior to each operation. We will create a new class that implements it and also make it an Attribute class so that we can decide which operation we want to track and decorate it. In order to use the previously implemented OperationInvoker class we will add some code in ApplyDispatchBehavior method to replace the default invoker with our own.

public class TrackingOperationBehaviorAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
    {

    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
    {
        TrackingOperationInvoker invoker = new TrackingOperationInvoker(dispatchOperation.Invoker);
        invoker.OnInvokeEnded += (sender, args) => { /* Log the call and execution time */ };
    }

    public void Validate(OperationDescription operationDescription)
    {

    }
}

You can put whatever logic you find fit in the commented part of the code – log it in the Windows EventLog, dump it in a database or a file. You could go even further and log the name of the operation, what parameters it was called with, etc. I haven’t implemented that here because I focused on tracking the code execution time only but it’s not that difficult to be implemented.

Summary

In this post I tried to present one simple solution to a trivial problem. WCF provides great extensibility options to developers and everything looks so elegant at the end. If you need to add a new operation to your service and track its execution time – no problem you just go there and decorate it with that attribute. That’s all you have to do, pretty neat 🙂

Advertisements
Categories: CSharp, WCF

ASP.NET MVC 3: Unobtrusive Client Side Validation

June 6, 2011 6 comments

In this post we will look at one of the new features of the fresh new release of ASP.NET MVC 3 – using unobtrusive client side validation through the new HTML5 data-* attributes. I will show what these attributes look like and how they come into play.

Client Validation by Default

One of the main differences between the new version and the previous two MVC 1 and MVC 2 is that client side validation is turned on by default. This is done using an AppSetting in the web.config file:

<appSettings>
  <add key="ClientValidationEnabled" value="true"/>
</appSettings> 

If you remember up until ASP.NET MVC 3 you had to explicitly specify that you want client side validation to be performed like this in your view:

<% Html.EnableClientValidation(); %>

If you don’t want any validation in the browser you could turn it off by changing the AppSetting value of ClientValidationEnabled to false.

Unobtrusive Validation

Validation in ASP.NET MVC is based on meta data provided by DataAnnotations. There are quite a few classes that are really handy in describing what rules your properties must obey and the framework will take care of the rest. The HTML Helper classes (Html.TextBoxFor, Html.EditorFor, etc.) used to render different HTML controls look up these meta data attributes when the response is being generated and render the appropriate output so that validation can occur on the client’s browser.

By taking advantage of Unobtrusive JavaScript you don’t clatter your HTML markup with unnecessary JavaScript event handlers and so on. The HTML elements describe themselves through attributes and you get a HTML5 ready markup by default. Here is a sample UserModel class that I will use in a create user form annotated with validation attributes:

public class UserModel
{
    [Required]
    [StringLength(50)]
    public string Username { get; set; }

    [Required]
    public string Password { get; set; }

    [Required]
    [Compare("Password")]
    public string ConfirmPassword { get; set; }

    [Required]
    [StringLength(50)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(50)]
    public string LastName { get; set; }

    [Required]
    [StringLength(50)]
    [RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$")]
    public string Email { get; set; }
}

When the user tries to submit the form with invalid data he/she will see the following messages:

Unobtrusive Client Side Validation

If we look at the confirm password input element for example we will see the following HTML markup:

<div class="editor-field">
    <input type="password" name="ConfirmPassword" id="ConfirmPassword" data-val-required="The ConfirmPassword field is required." data-val-equalto-other="*.Password" data-val-equalto="&amp;#39;ConfirmPassword&amp;#39; and &amp;#39;Password&amp;#39; do not match." data-val="true">
    <span data-valmsg-replace="true" data-valmsg-for="ConfirmPassword" class="field-validation-valid"></span>
</div>

As you can see there are a few data-val* attributes that add meta data to both this field and the span element that shows validation messages. Behind the scenes ASP.NET MVC uses jQuery Validation plugin and the Unobtrusive validation support library for jQuery Validate written by Microsoft. If you however decide to turn unobtrusive validation off your HTML markup won’t include the new HTML5 data-* attributes but a JavaScript code that will set up the Validation plugin.

For the ConfirmPassword property I have used one new attribute that comes with this new release part of .NET Framework 4.0 – CompareAttribute. It gives you the ability to compare two properties of a model.

Summary

As you can see ASP.NET MVC 3 is not lagging behind the current trends in web development utilizing some of the new HTML5 features and unobtrusive JavaScript. What I like about ASP.NET MVC and DataAnnotations is that we as developers don’t need to focus and waste too much time on simple validations like required fields, maximum length, etc. and focus on the business logic and any business rules that need to be enforced.

Architecting Loosely Coupled ASP.NET MVC Web Applications Talk

June 6, 2011 1 comment

Last week Kaloyan Bochevski and I gave a talk for the Web Platform User Group at Microsoft, Bulgaria. The topic was Architecting Loosely Coupled ASP.NET MVC Web Applications. For both of us it was quite an interesting experience as it was our first presentation and we for sure have a lot to improve for any future talks we might have.

The agenda

Our agenda covered a lot of areas even though it was mainly focused on how to design a loosely coupled ASP.NET MVC application. This was our list for the talk:

  • Dependency Injection with Spring.NET
  • Custom Authentication
  • Custom Attributes
  • jQuery Grid with Model Binders
  • Unobtrusive Validation with Data Annotations
  • Security (XSS Anti-Forgery token)
  • Covariance & Contravariance – IQueryable<out T> interface in .NET 4.0 and extension methods for .NET 3.5
  • Unit testing (NUnit, Selenium)

Over the next few weeks we will post articles that cover some of the bullets in the list. Any comments would be greatly appreciated.

ASP.NET: PostBackUrl and How It Can Break ViewState

February 15, 2011 1 comment

I hadn’t done pure ASP.NET Web Forms development for quite a while and I had to create a really simple edit form. The requirement was to show a confirmation message if there are unsaved changes when the user clicks on a button which would redirect him to another page. It’s really straight forward but as most seemingly simple things it turned out that it is somewhat trickier. I will explain every step I took down the road to get it done and what problems I encountered.

Buttons and PostBackUrl

I started with two buttons on the page:
Save button that triggers a postback to the server and persist the changes that the user made
Return button that posts back to the previous page – has its PostBackUrl property set to the url of the corresponding page

Then I wrote some JavaScript code that detects if there is any kind of change between the initial state of the page data and the current one when the user clicks the Return button. If nothing is changed the user was taken to the previous page. So far so good. But if there are some changes a confirmation message appears (I’m using a custom modal dialog, not the default browser’s confirmation dialog implementation) that notifies the user of unsaved pending changes and whether or not he/she wishes to navigate away from the current page anyway. This is where everything goes wrong. By default the ASP.NET Button control renders some JavaScript code for the click event of the button when PostBackUrl is set and it is executed regardless of my event handler.

Note: I am not attaching event handlers directly as attributes on DOM elements. Had I done this nothing would have messed up in my page. But this is really a bad way of doing client side development that is against unobtrusive JavaScript style.

Anyway this JavaScript code changes the form element’s action attribute with the value set for PostBackUrl and if the user decides that he/she wants to stay on the page and to save his/her changes the next time he/she clicks the Save button it will try to post back to the wrong page. Let’s say my page is called Default.aspx and I have another page Defautl2.aspx. Here is the rendered button:

<input type="submit" id="btnReturn" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnReturn", "", false, "", "Default2.aspx", false, false))" value="Return" name="btnReturn">

As you can see there is a JavaScript function WebForm_DoPostBackWithOptions that gets called and receives a single parameter a helper object with all the necessary data to initiate a post back. As you can see the fifth parameter for the WebForm_PostBackOptions constructor is the page to which the post back would occur. Inside the WebForm_DoPostBackWithOptions the action attribute of the page’s form element is changed to Default2.aspx. This won’t be a problem if I was not preventing the postback from occurring. However I do prevent it and from now on any subsequent postback triggered by a control on the page would post back to Default2.aspx. But since the ViewState of the first page differs from that of the second one an exception is thrown:

Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.

What is my solution then?

New form element

I decided to go for a solution with another form element for the second page and get rid of the PostBackUrl property on the button. Now when the user decides not to leave the page no JavaScript code changes the action attribute of the form element and everything is the way it is supposed to be. If he/she chooses to go ahead and go to the previous page then the second form element is submitted and the user is taken to the previous page. Keep in mind that you should not define more than one form server element with runat=”server” attribute because ASP.NET supports only a single form element. You could either create it as a standard HTML element or add it dynamically on the page.

Summary

This is not the first time I encounter this kind of exception but it was the first time I did for this kind of scenario and I was a bit puzzled in the beginning. So I needed to inspect what was going on behind the scenes and come up with a simple and quick solution. It was obvious that something is wrong when the button is clicked and debugging the injected function that makes the actual postback revealed it. There might be more elegant and clean solutions for resolving this issue so everyone is welcomed to share them.

Categories: ASP.NET, CSharp, JavaScript

DataAnnotations in Interfaces with Extension Methods

January 27, 2011 Leave a comment

Today’s blog post is about encapsulating validation rules in interfaces. If you are to develop a loosely coupled, unit-testable application you are for sure going to use some Dependency Injection framework (take a look at this post for Spring.NET by Kaloyan Bochevski). In order to accomplish this you start by designing some interfaces for your different logical layers. There you end up with interface contract definitions which must be implemented by your classes. You could even go further than just declaring some methods and properties and put validation rules there. This way you would encapsulate almost everything in the interface contract so it wouldn’t be spread across different class files or assemblies.

Data Annotations

DataAnnotations provide a great way of performing validation over data models in ASP.NET MVC and ASP.NET WebForms. Just by decorating your entity classes’ properties with the necessary attributes you can get out of the box validation with no code at all. These special attribute classes can be found in System.ComponentModel assembly which needs to be referenced from your project in order to get you ready to do your validations. In ASP.NET MVC this goes even further because you could enable even client side validation of your forms that are bound to data annotated models – the framework injects JavaScript code that handles all of this as long as you include some JavaScript files and enable client side validation. You could decorate your properties and make them required, fall in a specific range of values, have maximum number of characters or abide more complex rules with regular expressions. Here is what a sample entity interface definition might look like:

public interface IPerson : IValidationEntity
{
    [Required]
    string FirstName { get; set; }

    [Required]
    string LastName { get; set; }

    [Range(5, 100)]
    int Age { get; set; }

    [Required]
    [StringLength(20)]
    string City { get; set; }

    [Required]
    [StringLength(20)]
    string Country { get; set; }
}

If you are not developing against ASP.NET MVC or ASP.NET, let’s say for example you are doing a RESTful WCF service that needs to validate its input or you have some intermediary entities that are used to exchange information between different parts of a multi-layered system you could still take advantage of this validation model. Looking at the information for the System.ComponentModel.DataAnnotations Namespace at MSDN you can immediately see that all of the attributes derive from ValidationAttribute which has an IsValid() method. Basically we can get all validation attributes and check if the respective value is valid – this is how it works under the hood after all. Since we would have several classes that need to be validated then we need to create some common validation logic that we can reuse. This brings me to my next point.

Extension Methods

Extension methods provide a great deal of flexibility that I like to take advantage of whenever I can. In our scenario they will enable us to define some extensions over our interface and we will be able to validate all classes that implement this interface. First I’ll show you the definition of the interface:

public interface IValidationEntity
{
    bool Validate();
    IEnumerable<string> GetErrors();
}

There are only two methods that we need to develop:

public static class ValidationExtensions
{
    public static bool IsValid<T>(this T entity)
        where T : IValidationEntity
    {
        Type t = entity.GetType();
        Type[] tInterfaces = t.GetInterfaces();

        bool isValid = true;
        foreach (var ifc in tInterfaces)
        {
            foreach (var prop in ifc.GetProperties())
            {
                var propVal = prop.GetValue(entity, null);
                foreach (ValidationAttribute attr in prop.GetCustomAttributes(typeof(ValidationAttribute), true))
                {
                    if (attr.IsValid(propVal))
                        continue;

                    isValid = false;
                    break;
                }

                if (!isValid)
                    break;
            }

            if (!isValid)
                break;
        }

        return isValid;
    }

    public static IEnumerable<string> GetValidationErrors<T>(this T entity)
        where T : IValidationEntity
    {
        Type t = entity.GetType();
        Type[] tInterfaces = t.GetInterfaces();

        foreach (var ifc in tInterfaces)
        {
            foreach (var prop in ifc.GetProperties())
            {
                var propVal = prop.GetValue(entity, null);
                foreach (ValidationAttribute attr in prop.GetCustomAttributes(typeof(ValidationAttribute), true))
                {
                    if (attr.IsValid(propVal))
                        continue;

                    yield return attr.FormatErrorMessage(prop.Name);
                }
            }
        }
    }
}

IsValid checks if there are errors at all and GetValidationErrors returns a generic collection with descriptive error messages if we ever need to return some meaningful information (in case of a RESTful service). Both methods use reflection to get to the validation metadata that we have defined. The only interesting thing in the code above is that we need to iterate over the attributes of the class’s interfaces otherwise they won’t be available to us.

You could download a sample console application that utilizes the idea of defining validation rules on the interface.

Categories: CSharp

How to Handle Forms Authentication Timeout During an AJAX Request

October 26, 2010 3 comments

I stumbled upon an interesting issue the other day – how to respond to an error during an AJAX request after a period of user inactivity and a session expiration of the logged in user. In such situation you should either redirect the user to the login page or show a modal dialog where he/she could enter his or her credentials and continue their work. But this seemingly simple task turned out to be not so trivial. Here is the scenario:

  • the user logs in
  • after a period of inactivity the session times out
  • the user makes some action which triggers an AJAX request to the server which results in a response with a status code of 302 (Redirect) and the URL to the login page
  • the browser parses the response and issues a request to the provided redirection URL
  • the AJAX request completes, the response is the HTML markup of the login page with a status code of 200 (OK) which results in an error because the expected data type is JSON and it cannot be parsed correctly

The problem occurs during the last two points and the inability to determine the right cause of the error. It took me an hour or so to pinpoint and understand why this is happening. After this I tried some ideas and came up with a really simple solution.

What I needed was to pass the information to the XmlHttpRequest object that the user’s session had expired and to show a modal dialog so he or she could enter his or her credentials. That’s why I had to get rid of the redirection but only for AJAX requests because I still needed unauthenticated users to be redirected to the login page for non-AJAX requests. In order to do that I removed the Response.RedirectLocation in the Application_EndRequest event inside the Global.asax file:

protected void Application_EndRequest(object sender, EventArgs args)
{
    HttpContextWrapper context = new HttpContextWrapper(Context);
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
        context.Response.RedirectLocation = string.Empty;
}

After that it was easy to check the status code in the error handler of the AJAX request and since I knew that a 302 status code is sent by my application only when the user is not authenticated I was able to respond accordingly.

Categories: ASP.NET, ASP.NET MVC, CSharp

Performance tips – minification and deferred JavaScript loading

December 9, 2009 9 comments

In the past few years a lot of research has been done on page load times and where the hot spots occur. Surprisingly around 90% of the page load time is spent inside the browser. Why could this be happenning and what can be done in order to reduce these numbers?

How browsers work?

When a page is requested it is downloaded, parsed and rendered. During the rendering phase a lot is going on behind the scenes – static resources referenced by the page are downloaded, parsed and executed (in case of CSS and JavaScript). These static resources require additional HTTP requests which might dramatically slow down the loading of the page. Browsers have a limit of requests that could be performed in parallel, hence the resources are downloaded somewhat sequentially. The numbers differ from browser to browser, but in general two image files could be downloaded in parallel from a single domain, only a single JavaScript file could be downloaded at a time which also blocks the rendering of the page.

JavaScript hot spots

In this article the subject of interest are the bottlenecks that arise from requesting JavaScript files. There are different steps that could be taken to tune the page load time that is influenced by script files – minification and compression, combining all scripts in a single file (this is the recommended approach for CSS as well). There are several tools that are available for this purpose – JSMin and YUI Compressor (there is a .NET version that could be used in a MSBuild task) are some of them. You could make significant performance gains by minimizing and compressing – that could really be felt if your users are on a slow internet connection. By combining your scripts the browser will make only a single HTTP request which results in faster load times.

I will show you how to use YUI Compressor for .NET to combine and minify JavaScript files with MSBuild. To get started you need to copy Yahoo.Yui.Compressor.dll and EcmaScript.NET.modified.dll assemblies to your project. Create a so called project file (XML file that is constructed according to the MSBuild XML Schema definition) that is used to instruct the build engine what to do. I will not get into the details because MSBuild is not the subject of this post. Here is the project file:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
  <UsingTask
      TaskName="CompressorTask"
      AssemblyFile="Yahoo.Yui.Compressor.dll" />

  <Target Name="MyTaskTarget">
    <ItemGroup>
      <JavaScriptFiles Include="..\Scripts\jquery-1.3.2.js"/>
      <JavaScriptFiles Include="..\Scripts\MicrosoftAjax.js"/>
      <JavaScriptFiles Include="..\Scripts\MicrosoftMvcAjax.js"/>
    </ItemGroup>
    <CompressorTask
        CssFiles="@(CssFiles)"
        DeleteCssFiles="false"
        CssOutputFile="$(CssOutputFile)"
        CssCompressionType="YuiStockCompression"
        JavaScriptFiles="@(JavaScriptFiles)"
        ObfuscateJavaScript="True"
        PreserveAllSemicolons="False"
        DisableOptimizations="Nope"
        EncodingType="Default"
        DeleteJavaScriptFiles="false"
        LineBreakPosition="-1"
        JavaScriptOutputFile="$(JavaScriptOutputFile)"
        LoggingType="ALittleBit"
        ThreadCulture="en-us"
        IsEvalIgnored="false"
            />
  </Target>
</Project>

The important part is the ItemGroup element in which you specify the scripts that will be acted upon by YUI Compressor. Next you should edit the Build event script in order to run the MSBuild task. Right-click the project and choose Properties, then select Build Events. In the Post-build event command line enter the following script:

$(MSBuildBinPath)\msbuild.exe "$(ProjectDir)MSBuild\MSBuildXML.xml" /p:JavaScriptOutputFile="$(TargetDir)..\Scripts\JavaScriptFinal.js"
Project Properties - Build Events

Project Properties - Build Events

Now when you build your project your JavaScript files would be combined and minified – the output can be seen in this screenshot:

MSBuild output

MSBuild output

Another important aspect is where exactly in the page are the references for the JavaScript files. You should put them in the head section of the HTML document only if the scripts are essential for the page rendering phase (generation of HTML), otherwise you should put them at the end of the page to prevent blocking of the rendering. If you know that your script won’t be needed until a specific time on your page you could defer its loading. This way the browser won’t make a request for it and you will improve the page load time. It is really easy to accomplish – all you need to do is to attach an event handler to the onload event and download the file after a specified amount of time. Here is a sample HTML extension method for ASP.NET MVC that I wrote but this could be easily rewritten for ASP.NET:

private static string RegisterDeferredLoader(this HtmlHelper helper)
{
    HttpContextBase context = helper.ViewContext.HttpContext;
    if (context.Items.Contains("__DeferredLoader"))
        return "";

    context.Items.Add("__DeferredLoader", "__DeferredLoader");

    StringBuilder strBuilder = new StringBuilder();
    strBuilder.AppendLine("<script type=\"text/javascript\">");
    strBuilder.AppendLine("function loadScript(file){");
    strBuilder.AppendLine("var script = document.createElement('script');");
    strBuilder.AppendLine("script.type = \"text/javascript\";");
    strBuilder.AppendLine("script.src = file;");
    strBuilder.AppendLine("document.body.appendChild(script);");
    strBuilder.AppendLine("};");
    strBuilder.AppendLine("</script>");

    return strBuilder.ToString();
}

This private helper method outputs a JavaScript function on the page that initiates the request for the script file itself – it simply creates a SCRIPT DOM element and sets its src attribute to the URI of the file. When it is appended to the document the script file is downloaded automatically. The method also ensures that the JavaScript function is written only once in the HTML document – we do not want it multiple times which increases the overall size of the document that would be transferred.

Here is the extension method that would be used to defer the loading of scripts on the page:

public static string RegisterScript(this HtmlHelper helper, string resourceUri, int delayInMilliseconds)
{
    HttpContextBase context = helper.ViewContext.HttpContext;
    if (context.Items.Contains(resourceUri))
        return "";

    context.Items.Add(resourceUri, resourceUri);
    StringBuilder strBuilder = new StringBuilder();
    strBuilder.AppendLine(helper.RegisterDeferredLoader());

    strBuilder.AppendLine("<script type=\"text/javascript\">");
    strBuilder.AppendFormat("if (window.addEventListener) window.addEventListener('load', function(){{window.setTimeout(function(){{loadScript(\"{0}\");}}, {1});}}, false);", resourceUri, delayInMilliseconds);
    strBuilder.AppendFormat("else if (window.attachEvent) window.attachEvent('onload', function(){{window.setTimeout(function(){{loadScript(\"{0}\");}}, {1});}});", resourceUri, delayInMilliseconds);
    strBuilder.AppendLine("</script>");

    return strBuilder.ToString();
}

This method outputs JavaScript code that attaches an event handler to the onload event of the window in which the loadScript function is called after a specified number of milliseconds. As you can see all of this is accomplished with a minimum amount of code and there is no complex logic. In order to use the extension method in your pages you should add its namespace to the pages/namespaces element inside the web.config file:

<pages>
    ...
    <namespaces>
        ...
        <add namespace="JSOptimizations.Helpers"/>
    </namespaces>
</pages>

What follows is a simple test of the extension method. This is a very simple JavaScript file that renders the time at which it is executed:

document.body.innerHTML += 'I am now loaded at ' + new Date();

And the HTML for the page is as follows:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!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 runat="server">
    <title>DeferLoading</title>
    <%= Html.RegisterScript("../../Scripts/DeferLoading.js", 5000) %>
</head>
<body>
    <script type="text/javascript">
        document.body.innerHTML += 'Page is rendered at: ' + new Date() + '<br/>';
    </script>
</body>
</html>

When you open it you would see something similar to the screenshot:

Deferred Loading of JavaScript

Deferred Loading of JavaScript

As you can see the JavaScript file is loaded exactly 5 seconds after the page is rendered.

You could download the sample test project with both the MSBuild task and the extension methods from here.

Summary

Simply by utilizing some techniques for loading JavaScript files you could dramatically increase the load times of your pages. Both minifying and combining several files into a single one can save significant amount of bandwidth. Deferred loading allows you to download scripts after the page has loaded thus reducing the network round trips to the server while rendering the page. There is no single golden rule that will help you achieve the best performance but when you use different techniques for your specific scenario you could really make great improvements.