Category Archives: ASP.NET

Cancelling Long Running Couchbase N1QL Queries

Overview

The recent release of the Couchbase .NET SDK 2.4.0 has added many new features.  There is a minor feature, however, that is worth a mention.  It’s now possible to cancel long-running N1QL queries.

For example, in a web application a user might browse away from the page in impatience.  When they do, you don’t want  the query to keep executing pointlessly.  Instead, you can cancel the query, freeing web server and Couchbase  server resources for other requests.

How To Cancel

Using this new feature is very easy, when executing your query simply supply a CancellationToken.  For web applications, this can be acquired by including a CancellationToken as a parameter on an asynchronous action method.

public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    var bucket = ClusterHelper.GetBucket("my-bucket");
    var query = new QueryRequest("SELECT * FROM `my-bucket` WHERE type = 'docType' LIMIT 1000");

    var result = await bucket.QueryAsync<Document>(query, cancellationToken);
    if (result.Success) {
        return Json(result.Rows);
    }
}

Compatibility

Note: Documentation on what versions of ASP.NET MVC and Web API support CancellationToken is a bit sparse.  Apparently some versions only use it for timeouts (using  AsyncTimeout), while some versions have support for cancellations from the browser.  There is also a way to add support for browser cancellation using CreateLinkedTokenSource.

The behavior may also depend on the web server you’re using (i.e. IIS versus Kestrel, and Kestrel version). For example, this change to Kestrel appears to cause client disconnects to do a better job of triggering the CancellationTokken. If anyone knows more details about version support, please let me know and I’ll update the post.

MVC 3 Unobtrusive AJAX Improvements

I started experimenting this week with MVC 3 and the new unobtrustive javascript frameworks, both for AJAX and validation. These are built around jQuery, and frankly are very nice pieces of work. There are, however, a few improvements that can be made to the Javascript files included in the distribution. You can obviously include these changes manually, it’s pretty simple, but hopefully one day Microsoft will roll these up in the next version.

I’m not sure how the unobtrusive stuff is licensed by Microsoft, so I won’t publish the modified code here until I’m certain it’s okay. I will, however, go over the modifications so that you can do them yourselves.

  1. Use fn.delegate instead of fn.live – By default, the unobtrusive AJAX library uses fn.live to monitor for anchor click and form submit events, and if the elements are set to operate using AJAX they are intercepted and an AJAX request is initiated.  However, this can be inefficient because the selector is actually being fired during during document.ready, even though it isn’t used for anything.  This means every single form, submit button, and link on your page is being checked for a data-ajax=”true” attribute during document.ready for no reason.  By using $(document).delegate(selector, eventType, fn) this is completely avoided. Note: This only works using jQuery 1.4.2 or later.
  2. Cache jQuery Objects – While this is a minor efficiency concern, there are several places with the event handlers where $(form) is called multiple times to convert an element into a jQuery object with a single member.  It is much more efficient to cache $(form) in a local variable and reuse it. You can also make finding the form more efficient using .closest(‘form’) instead of .parents(‘form’)[0].
  3. Inefficient Handling Of Null Callbacks – asyncRequest uses getFunction to get a callback function based on data attributes.  This is nifty system, because can take either a function name or inline javascript code.  However, if there is no function specified, it goes through the trouble of using Function.constructor to create an empty function.  This can be avoided by adding “if (!code) return $.noop;” to the beginning of getFunction.
  4. Global AJAX Events – Currently, there is no way to attach global AJAX event handlers that specifically handle only the MVC related AJAX events.  Your only options are to intercept ALL jQuery AJAX events, or to attach events to each specific AJAX request using data attributes.  However, there are definitely use cases for global event handlers that only affect MVC related AJAX events.  Therefore, I recommend updating the “asyncRequest” function to add information to the options passed to $.ajax.  In particular, during the $.extend(options, {…}) I am adding “mvcRequest: true” and “mvcTargetElement: element”.  Now you can attach global jQuery AJAX handlers using $(document).ajaxSuccess, etc, and then test to see if it is an MVC request.
  5. AJAX Updated Forms Validation – In the current implementation of the unobtrusive validation, it can’t handle forms added to the page via an AJAX request.  You have to manually call $.validate.unobtrusive.parse() after the page update before client-side validation resumes.  This can be addressed using a global handler, so long as #3 above is also implemented.  By using the attributes passed in, we restrict the processing so it doesn’t re-parse the entire document, only the updated region. The code for this is below:
$(document).ajaxSuccess(function (event, xhr, settings) {
    if (settings.mvcTargetElement) {
        $(settings.mvcTargetElement.getAttribute("data-ajax-update")).each(function () {
            $.validator.unobtrusive.parse(this);
        });
    }
});

Please let me know if you see any other improvements that I’ve missed. I’m just beginning to dig through things, so I’ll keep updating as I find more as well.

Simplify Asynchronous Javascript Loading In ASP.Net Using LABjs

LABjs is an excellent javascript library that performs asynchronous loading of javascript files. This can help to greatly increase the load speed of your web pages. Now, instead of blocking while one file is being downloaded, other scripts further down the chain can be downloaded while waiting. On top of that, it can maintain processing order, waiting to process certain scripts until others are complete, and optionally executing code on completion.

All of this is great for the client side. But how do you define which scripts to include in the LABjs chain on the server side?

Since for work I primarily operate in ASP.Net, I’ve created an ASP.Net solution to the problem, LABjs.Net. This library provides two key controls, LabScriptManager and LabScriptManagerProxy. These controls loosely follow the behavior of the AJAX ScriptManager and ScriptManagerProxy controls, at least their script loading aspects.

Key supported features include:

  1. Refer to script files using application relative paths (i.e. ~/js/jquery.min.js)
  2. Load script files from assembly resources
  3. Specify if debug or release scripts should be used, or use the debug setting from the web.config file
  4. Ability to set any of the options provided by LABjs
  5. Include wait() calls in the chain, and provide inline functions to be executed after the wait
  6. Use LabScriptManagerProxy to add scripts and waits to the chain in content pages and user controls
  7. Use LabActionGroup inside LabScriptManagerProxy to add script() calls at a specific point in the primary chain
  8. LABjs debug and release versions are embedded in the DLL and automatically referenced, but you can opti0nally override this with your own URL
  9. Experimental support for the cdnLABjs library I am working on, which provides automatic failover to a local file if a file fails to load from a CDN (for information about why, see Using CDN Hosted jQuery with a Local Fall-back Copy)

Below you will find links to the current release candidate, 1.0rc1.  Please review it and give me any feedback you might have.

Download Binaries
Readme File
Git Repository

Update 2/8/2010: Updated to version 1.0rc4

jQuery.Net

In the last few months, I’ve discovered jQuery and jQuery UI, which are a pair pretty awesome of open source javascript libraries.  I know, I’m a little behind the times here, but all I can say is “Wow”.  Frankly, using jQuery makes the AJAX library that comes with .NET 3.0/3.5 from Microsoft seem foolish and clunky.  I’ve now transitioned away from using Microsoft’s open source AJAX Control Library, instead choosing to use jQuery.

The only downside of using jQuery with ASP.Net is the lack of integration.  They now include a vsdoc file which helps with Intellisense, but there’s a long way to go.  For simplicity, I’m still using Microsoft’s AJAX code for their page methods and UpdatePanels, and primarily using jQuery for the client side controls and animations.

I’ve written a library to help with the creation of ASP.Net server controls that utilize jQuery.  I’m calling it, very creatively, jQuery.Net.  You can access the code and binaries for the library on github, the link’s below.

jQuery.Net Git Repository

Appending Text To The Titles Of All Web Pages

Have you ever wanted to add a text string, like an application name, to the title of all your web pages. It’s easy to do using the control adapters available in ASP.NET 2.0 and later. First, create a new .browser file in the App_Browsers folder of your application, or add this entry to an existing file. Be sure to substitute MyNamespace for the correct namespace where the class is located.

<browsers>

  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.HtmlControls.HtmlHead"
               adapterType="MyNamespace.TitleAdapter" />
    </controlAdapters>
  </browser>

</browsers>

Now create the TitleAdapter class that is referenced by the .browser file:

Imports System.Web.UI.Adapters

Public Class TitleAdapter
    Inherits ControlAdapter

    Private Shared _titleAppendString As String = " - Your Application Name Here"
    Public Shared Property TitleAppendString() As String
        Get
            Return _titleAppendString
        End Get
        Set(ByVal value As String)
            _titleAppendString = value
        End Set
    End Property

    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.Render(New TitleAdapterHtmlTextWriter(writer, TitleAppendString))
    End Sub

End Class

And finally, create the HtmlTextWriter that is referenced by the control adapter:

Public Class TitleAdapterHtmlTextWriter
    Inherits HtmlTextWriter

    Public Sub New(ByVal writer As HtmlTextWriter, ByVal appendString As String)
        MyBase.New(writer)
        InnerWriter = writer.InnerWriter

        _appendString = appendString
    End Sub

    Public Sub New(ByVal writer As System.IO.TextWriter, ByVal appendString As String)
        MyBase.New(writer)
        InnerWriter = writer

        _appendString = appendString
    End Sub

    Private _appendString As String

    Private _renderingTitle As Boolean = False
    Private _nestedCount As Integer

    Public Overrides Sub RenderBeginTag(ByVal tagName As String)
        If _renderingTitle Then
            _nestedCount += 1
        ElseIf String.Equals(tagName, "title", StringComparison.InvariantCultureIgnoreCase) Then
            _renderingTitle = True
            _nestedCount = 0
        End If

        MyBase.RenderBeginTag(tagName)
    End Sub

    Public Overrides Sub RenderBeginTag(ByVal tagKey As System.Web.UI.HtmlTextWriterTag)
        If _renderingTitle Then
            _nestedCount += 1
        ElseIf tagKey = HtmlTextWriterTag.Title Then
            _renderingTitle = True
            _nestedCount = 0
        End If

        MyBase.RenderBeginTag(tagKey)
    End Sub

    Public Overrides Sub RenderEndTag()
        If _renderingTitle Then
            If _nestedCount > 0 Then
                _nestedCount -= 1
            Else
                _renderingTitle = False
                Write(_appendString)
            End If
        End If

        MyBase.RenderEndTag()
    End Sub

End Class

Note that you can edit the text string in the TitleAdapter class. Additionally, it is a static variable so you can alter it at startup from a database column in your Global.asax file.