|
|
Encosia
|
| http://encosia.com |
| ASP.NET and AJAX code, ideas, and examples. |
|
|
|
|
|
|
|
|
|
Continuing my series of posts about ASMX services and JSON, in this post I’m going to cover two common mistakes that plague the process of getting a project’s first ASMX ScriptService working: Installing System.Web.Extensions into the GAC and configuring your web.config.
System.Web.Extensions (aka ASP.NET AJAX)
The ability for ASMX services to return raw JSON is made possible by two key features originally added by the ASP.NET AJAX Extensions v1.0:
- JavaScriptSerializer – The JavaScriptSerializer class is the actual workhorse that translates back and forth between JSON strings and .NET CLR objects. Though less powerful than WCF’s DataContractJsonSerializer and third-party libraries like Json.NET, JavaScriptSerializer is likely all you’ll ever need for simple AJAX callbacks.
- ScriptHandlerFactory – There are several more classes behind the scenes*, but the ScriptHandlerFactory is the tip of the iceberg that you’ll need to remember during configuration. Redirecting ASMX requests through this HttpHandler is what coordinates the pairing of ScriptService with JavaScriptSerializer to provide automatic JSON handling.
Though both of these classes appear in the System.Web.Script namespace, they actually reside in ASP.NET AJAX’s System.Web.Extensions assembly. That has different implications depending on which version of ASP.NET your site targets:
- 1.x – No support for ScriptServices. A custom HttpHandler coupled with a third party library like Json.NET is your best bet (if anyone has a good tutorial on doing this under 1.x, let me know so that I can link to it).
- 2.0 – ScriptServices are available in ASP.NET 2.0 with the installation of the ASP.NET AJAX Extensions v1.0.
- That means that the ASP.NET AJAX installer needs to be run on the server that hosts your site, not just on your local development machine.
- For some of a ScriptService’s features to work in medium trust (i.e. shared hosting), the System.Web.Extensions assembly needs to be in your server’s global assembly cache (GAC). Don’t waste your time trying to make it work in your site’s /bin directory; insist that the extensions be properly installed on the server.
- 3.5+ – As of .NET 3.5, System.Web.Extensions ships with the framework. No additional assemblies need be installed.
* If you’re interested in the internals, I highly recommend downloading the ASP.NET AJAX Extensions v1.0 source and taking a look at ScriptHandlerFactory, RestHandlerFactory, and RestHandler. Though the classes have changed slightly since v1.0, they are still very similar.
Rerouting the ASMX handler via web.config
With the System.Web.Extensions assembly installed in the GAC, the remaining configuration step is an element in your site’s web.config. To take advantage of the ScriptService functionality, ASP.NET must be instructed to reroute ASMX requests through the ScriptHandlerFactory instead of ASP.NET’s standard ASMX handler.
This step is often unnecessary. The project templates in ASP.NET 3.5+ include all the necessary configuration elements, and ASP.NET 2.0 sites created with the “AJAX Enabled” templates are also pre-configured correctly.
However, if you find yourself unable to coax JSON out of an ASMX ScriptService, verifying your web.config is one of the best first steps in troubleshooting the issue. Whether due to a web.config generated by an older project template, accidental modification, or other issues, missing the httpHandlers web.config setting is a very common pitfall.
What should appear varies slightly depending on which version of ASP.NET your project targets. Regardless of your framework version, the config elements should be added to the <httpHandlers> section and are the only elements necessary. The variety of other config items required for the UpdatePanel and ScriptManager aren’t crucial to the ScriptService functionality.
ASP.NET 2.0 (with the ASP.NET AJAX Extensions installed)
<configuration>
<system.web>
<httphandlers>
<remove path="*.asmx" verb="*" />
<add path="*.asmx" verb="*" Culture=neutral, validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
PublicKeyToken=31bf3856ad364e35" />
</httphandlers>
</system.web>
</configuration>
ASP.NET 3.5
<configuration>
<system.web>
<httphandlers>
<remove path="*.asmx" verb="*" />
<add path="*.asmx" verb="*" Culture=neutral, validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0,
PublicKeyToken=31bf3856ad364e35" />
</httphandlers>
</system.web>
</configuration>
ASP.NET 4
Thankfully, ASP.NET 4 has taken steps to reverse the trend of ever-enlarging baseline web.config files. By moving common configuration items such as the ScriptService’s HttpHandler to the default machine.config, each individual site need not include those configuration elements in their specific web.config files.
Unless you go out of your way to manually remove their HttpHandler, ASMX ScriptServices will work automatically in any ASP.NET 4 site.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
ASMX ScriptService mistakes: Installation and configuration
 |
|
|
|
|
|
|
|
While we were recording episode 5 of Mastering jQuery, I found myself running down a lengthy list of misconceptions and potential pitfalls when it comes to using ASMX services for AJAX callbacks. After years of fielding questions revolving around that topic, I suppose I’ve developed a decent handle on the issues most often encountered.
To preemptively surface some of that commonly requested information, I’m going to publish a series of relatively short posts, each describing one mistake or misconception that I’ve seen come up frequently.
To get started, I want to cover one of the most fundamental of these misconceptions: That ASMX services can’t return JSON.
Misconception: ASMX services are limited to XML
One of the most stubbornly persistent misconceptions about ASMX services is the rumor that they are limited to returning XML. With that notion mind, many developers understandably avoid them for client-side AJAX callbacks. When every byte counts, raw JSON is always preferable to the bloat of XML.
However, the introduction of ASP.NET AJAX removed that XML limitation.
In any ASP.NET 2.0+ AJAX enabled site, one of ASP.NET AJAX’s additions is something called the ScriptService. When a ScriptService is called in the correct manner, it automatically returns its result serialized as JSON instead of XML.
In fact, these ASMX ScriptServices even accept their parameters as JSON.
The ASP.NET AJAX “ScriptService”
If you’ve created an ASMX service in the past few years, you’ve probably seen this blurb at the beginning of the default template:
// To allow this Web Service to be called from script,
// using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
Since it never explicitly mentions JSON and implies a tight coupling with ASP.NET AJAX, it’s easy to understand why the ScriptService’s true power sometimes goes unnoticed. Thankfully, that attribute does much more than simply expose ASP.NET AJAX specific functionality.
In fact, the ScriptService attribute enables all of an ASMX service’s methods to respond with raw JSON if they are requested correctly. For example, these ScriptServices can easily send and receive JSON in conjunction with a third party library, without a ScriptManager or MicrosoftAjax.js anywhere to be seen.
Two simple requirements
As I alluded to earlier, the one stipulation is that these ScriptServices only return JSON serialized results if they are requested properly. Otherwise, even a service marked with the attribute will return XML instead of JSON. I can only assume that’s part of the reason for the misconception that ASMX services cannot respond with JSON.
Scott Guthrie has a great post on the specific requirements for coercing JSON out of ScriptServices. To summarize that, requests to the service methods must meet two requirements:
- Content-Type – The HTTP request must declare a content-type of application/json. This informs the ScriptService that it will receive its parameters as JSON and that it should respond in kind.
- HTTP Method – By default, the HTTP request must be a POST request. It is possible to circumvent this requirement, but it is advisable to stick with HTTP POST requests when dealing with JSON.
That’s it.
As long as those two requirements are satisfied, anything from low-level XMLHttpRequest code, to third-party libraries like jQuery, to ASP.NET AJAX itself can easily retrieve JSON serialized data from ASMX services.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
ASMX and JSON – Common mistakes and misconceptions
 |
|
|
|
|
|
|
|
If you’ve already begun using Microsoft’s new Ajax Script Loader with a CDN-hosted version of jQuery, today’s release of jQuery 1.4 may have left you wondering how to upgrade. Personally, I didn’t want to wait on a new version of Start.js, nor did I want to abandon the script loader now that I’ve become accustomed to its benefits.
No doubt, an upcoming ASP.NET Ajax Library iteration will update Start.js’ jQuery definition to reference jQuery 1.4.x. Regardless, knowing how to patch the script loader on your own terms is something that will be of recurring usefulness.
Luckily, the script loader is open and extensible enough that it’s possible to change which script versions are used. So, I want to briefly show you how the script loader defines JavaScript includes and how you can patch those definitions without modifying Start.js itself.
Using the script loader to inject jQuery
If you aren’t familiar with the script loader itself or with using it to asynchronously request jQuery, I recommend checking out its documentation and examples on the new ASP.NET Ajax Wiki.
To use it most basically, simply include a reference to Start.js either locally or on the Microsoft CDN, and then use this JavaScript to instruct the script loader to inject jQuery into the page:
// Instruct the script loader to request
// jQuery in the background.
Sys.require(Sys.scripts.jQuery);
// This callback runs later, after jQuery
// has been asynchronously loaded.
Sys.onReady(function () {
console.log("Loaded jQuery " + jQuery.fn.jquery);
});
Monitoring the request in Firebug illuminates what that Sys.require statement triggered in the background:

As you can see, the end result is pretty straightforward. The primary benefit of this asynchronous loading technique is that scripts loaded through the script loader are non-blocking and may be loaded in parallel. By contrast, JavaScript includes referenced through HTML script elements block all rendering and further requests until they are parsed and executed. The difference is often significant.
Now, if only it were injecting jQuery 1.4 instead of 1.3.2.
Understanding how Sys.scripts.jQuery is defined
The Sys.scripts.jQuery parameter to the script loader is actually just a JavaScript object that defines a few parameters about the include. Here is how that is defined in Start.js (edited slightly for readability here):
var path = (window.location.protocol === "https" ? "https" : "http")
+ "://ajax.microsoft.com/ajax/";
loader.defineScripts(null, [
{ name: "jQuery",
releaseUrl: path + "jquery/jquery-1.3.2.min.js",
debugUrl: path + "jquery/jquery-1.3.2.js",
isLoaded: !!window.jQuery
}
]);
If you’re using a local copy of Start.js, one option is to modify this jQuery script definition inside Start.js itself. However, I discourage that alternative. Not only would it require constant, manual maintenance after every new release, but it isn’t an option when using the Microsoft Ajax CDN’s copy of Start.js.
Defining a new target for it
Another option is to simply modify the Sys.scripts.jQuery object itself. Letting Start.js initialize the definition with jQuery 1.3.2’s path doesn’t hurt anything as long as we redefine it before calling Sys.require.
Inspecting the Sys.scripts collection in Firebug reveals how straightforward that modification will be:

Thanks to to the power of interactively interrogating the object in Firebug, it becomes clear that updating the releaseUrl and debugUrl properties of that object should be all that is necessary.
Updating the example to use jQuery 1.4
Because jQuery 1.4 isn’t available on the Microsoft CDN yet, I’m going to target Google’s AJAX Libraries CDN for jQuery instead. Once Microsoft’s CDN is updated with jQuery 1.4.x, this approach will work for either CDN.
// These re-definitions must be executed after
// Start.js, but before Sys.require.
var CDN = "http://ajax.googleapis.com/ajax/libs";
Sys.scripts.jQuery.releaseUrl = CDN + "/jquery/1.4.1/jquery.min.js";
Sys.scripts.jQuery.debugUrl = CDN + "/jquery/1.4.1/jquery.js";
// Instruct the script loader to request
// jQuery in the background.
Sys.require(Sys.scripts.jQuery);
// This callback runs later, after jQuery
// has been asynchronously loaded.
Sys.onReady(function () {
console.log"Loaded jQuery " + jQuery.fn.jquery);
});
That’s all there is to it. Reviewing the requests in Firebug again, you can see that the same Sys.require statement is indeed now loading jQuery 1.4 from Google’s CDN:

Bonus: jQuery Validate 1.6
As I write this, Start.js’ definition for Sys.scripts.jQueryValidate is still targeting version 1.5.5 of the plugin, but 1.6 is the current version.
Using what’s been covered in this post, pointing the script loader at the newest version of jQuery Validate is no problem:
var MSCDN = "http://ajax.microsoft.com/ajax";
var GoogCDN = "http://ajax.googleapis.com/ajax/libs";
// Please forgive my ugly formatting to make this fit. Do not try
// this at home (unless your editor is only 492px too).
Sys.scripts.jQuery.releaseUrl =
GoogCDN + "/jquery/1.4.1/jquery.min.js";
Sys.scripts.jQuery.debugUrl =
GoogCDN + "/jquery/1.4.1/jquery.js";
Sys.scripts.jQueryValidate.releaseUrl =
MSCDN + "/jQuery.Validate/1.6/jQuery.Validate.min.js";
Sys.scripts.jQueryValidate.debugUrl =
MSCDN + "/jQuery.Validate/1.6/jQuery.Validate.js";
// Instruct the script loader to request
// jQuery and jQuery Validate in the background.
Sys.require([Sys.scripts.jQuery, Sys.scripts.jQueryValidate]);
// This callback runs later, after both jQuery
// and jQuery Validate have been loaded.
Sys.onReady(function () {
console.log("Loaded jQuery " + jQuery.fn.jquery);
});
The jQuery Validate situation is a good example of why knowing how to update these script definitions yourself is worthwhile. Because the script loader was designed to be so flexible, there’s no need to wait on a new release of Start.js or give up its benefits.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
How you can force the Ajax Script Loader to use jQuery 1.4
 |
|
|
|
|
|
|
|
On this day in 2006, I wrote and published a short post here about something that had eluded my attempts at searching for an answer. I thought that archiving the information online might help if I needed to find it again later, and that it might help anyone else who had been similarly unable to track down the answer.
Three years later, the site has served over one million page views to JavaScript enabled browsers in the last year alone, and thousands of you keep tabs on the site’s updates through RSS, email, and/or Twitter.
One step at a time, it’s astonishing just how far this thing has come.
Best of 2009
Of the posts published since this time last year, these are the ones that have been viewed the most, starting with the most popular:
$(document).ready() and pageLoad() are not the same – The inclusion of LiveQuery in jQuery 1.3 makes pageLoad necessary less often, but it is still useful at times. Understanding when and where that makes sense is crucial when initializing jQuery functionality on content within UpdatePanels.
Automatically minify and combine JavaScript in Visual Studio – I was never very happy with the various minification workflows I had tried before this. Combination was even worse. Finding this hybrid between the tedious configuration of build tasks and the waste of manual minification removed almost all the friction involved.
11 keystrokes that made my jQuery selector run 10x faster – This was probably the most self-educational post I wrote this year. Though the title may have been over-sensationalized, I hope all of the objective, cross-browser testing made it worth reading.
Simplify calling ASP.NET AJAX services from jQuery – This post represents the culmination of what went into at least three others before it (1, 2, 3). Though the end result would have been easy enough to publish for copy/pasting, I hope it was useful for me to “show my work” in the interim iterations.
Using complex types to make calling services less… complex – I’m happy to see this post in the top five, even though it’s more narrowly focused. I think it’s an important one for those of us using jQuery and ASP.NET AJAX services in non-trivial scenarios. In fact, someone described the approach in this post to me a few days ago as a “huge paradigm shift!”, which pretty well describes the impact it had in my own work.
Thank you
The past year has been a bit surreal for me, to say the least.
Since this time last year, I’ve joined with great co-authors on the second edition of a book that I was already a fan of, joined the ASPInsiders, received the ASP.NET MVP award, have had the opportunity to work with Craig Shoemaker and the guys at TekPub on branching out to different mediums, and have even more projects in the works that I can’t announce yet.
I could not have done it without you. Without your participation, promotion, and support over the past three years, none of the previous would have been possible at all; not by a long shot.
For all of the above, I am sincerely, profoundly grateful.
I hope that you enjoy a safe, happy holiday, and that we all have a great 2010 coming up. With Visual Studio 2010, .NET 4, and jQuery 1.4 coming in the first few months alone, it’s sure to be an interesting year!
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
3 years of Encosia, the best of 2009, and my gratitude
 |
|
|
|
|
|
|
|

If you haven’t been following the progress of Rob Conery and James Avery’s new venture, TekPub, you’ve been missing out on some great instructional videos. I especially like that they trend slightly Alt.NET, giving you more balanced information than is sometimes available from “official” .NET screencasts.
For the past few weeks, I’ve been working with James to record a series of episodes for TekPub myself: Mastering jQuery.
Mastering jQuery walks through the basics of using jQuery, the revolutionary JavaScript framework that makes writing client-side code fun and easy, and then dives into the details of writing AJAX enabled ASP.NET MVC and ASP.NET Web Forms applications. We will also cover popular plugins and extending jQuery in future episodes.
Today, the first video in that series is available: Getting Started with jQuery.
In this episode we cover the basics of getting started with jQuery. We start with a basic HTML page and show how to include jQuery, how to write your first code, and explain all of the moving pieces and how they work.
If you’ve been following my site and working with jQuery already, the first episode may sound elementary, but there’s going to be something for everyone before the series is finished. By the third episode, we’re already into topics like making AJAX calls to MVC controller actions and progressively enhancing an entry form with the jQuery form plugin.
I hope you’ll head over to TekPub, and have a look for yourself.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Mastering jQuery now available at TekPub
 |
|
|
|
|
|
|
|
In my most recent post, I demonstrated a workaround to allow using the jQuery validation plugin with WebForms pages. The basic idea was to trigger validation only on submissions that occurred within a single logical form, instead of catching submissions anywhere on WebForms’ all-encompassing physical form.
This approach worked fine for a single logical form, but wasn’t robust enough when handling validation for multiple logical forms on a single page. Additionally, it did not properly handle the enter key, allowing users to (perhaps accidentally) slip past validation if they simply hit the enter key within a TextBox.
In this post, we will continue by refining the solution from last time. So, if you haven’t read the previous post, familiarize yourself with it first. Specifically, this post will cover how to implement an analogue of WebForms’ ValidationGroup, use that to independently validate multiple form regions, handle the enter key, and refactor the final solution to minimize duplicated code.
ValidationGroups
In WebForms, we have the concept of a ValidationGroup to mitigate the issues that come with wrapping the entire page in a single form element. Whether right or wrong in principle, this scheme does a pretty good job of keeping the ASP.NET Validation controls from getting their wires crossed on complex forms.
However, using ASP.NET’s ValidationGroups requires that you use the WebForms validation controls, which generates quite a bit of cruft in your markup and injects two additional script references on your page.

If you’re like me, trying to trend away from client-heavy WebForms pages these side-effects are prohibitive.
Emulating Validation Groups
Though its implementation renders a bit messy on the client-side, the WebForms paradigm of a ValidationGroup is exactly what we need for segregating our physical form element into logical forms. In fact, I’m going to use the same nomenclature in this example (ValidationGroup and CausesValidation).
Using CSS classes as flags is a great way to emulate that concept in plain (X)HTML markup. Especially when using jQuery, CSS “flags” are a great way to tag elements with arbitrary attributes, that are easy to find with simple DOM selectors later. Taking the form shown in my previous post and tagging its fieldsets with a validationGroup class, we end up with this markup:
<fieldset class="validationGroup">
<legend>Returning customer? Login here</legend>
<!-- Username and Password labels and inputs here -->
</fieldset>
Not a very large change, but it allows us to keep these logical forms separate, both when performing validation and when initially setting up their validation triggers.
Creating a CausesValidation counterpart
ValidationGroups may control the organization of logical forms, but it’s the controls marked with the CausesValidation property that drive validation of those forms. In similar fashion, we need a way to indicate which elements should trigger our own emulation of WebForms’ grouped validation.
Sticking with the same naming scheme and CSS flagging technique, it makes sense to tag our Button controls with a .causesValidation class:
<fieldset class="validationGroup">
<legend>Returning customer? Login here</legend>
<!-- Username and Password labels and inputs here -->
<asp:Button runat="server" ID="Login" Text="Login"
CssClass="causesValidation" />
</fieldset>
Now we just need to wire up functionality to make those causesValidation flags actually do something.
Acting on the validationGroup flag
With the markup modified to allow selective targeting of the validation groups, the next step is implementing validation functionality that leverages that targeting. Using jQuery’s powerful CSS-based selectors, that isn’t difficult:
$(document).ready(function () {
$("#form1").validate({ onsubmit: false });
// Search for controls marked with the causesValidation flag
// that are contained anywhere within elements marked as
// validationGroups, and wire their click event up.
$('.validationGroup .causesValidation').click(function (evt) {
// Ascend from the button that triggered this click event
// until we find a container element flagged with
// .validationGroup and store a reference to that element.
var $group = $(this).parents('.validationGroup');
var isValid = true;
// Descending from that .validationGroup element, find any input
// elements within it, iterate over them, and run validation on
// each of them.
$group.find(':input').each(function (i, item) {
if (!$(item).valid())
isValid = false;
});
if (!isValid)
evt.preventDefault();
});
});
Note: For more explanation of any uncommented code above, be sure to see the previous post in this series. Those parts are explained in detail there.
This sets up a click event handler on any element flagged with the causesValidation class; the two Button controls in our case. When those raise click events, we start at the triggering element and use the parents() traversal method to search upward for the nearest parent flagged as a validationGroup.
In this example, that will find a reference to the fieldset which contains the Button control that triggers the click event (e.g. if the user clicks the Login Button, then $group will store a reference to the first fieldset element).
With that reference to the the logical form requiring validation, jQuery’s find() traversal method allows us to select a set of all the input elements within just that region of the page. Note that this will also include the Button control that triggered the event, but since the valid() method returns true for elements that don’t have validation rules configured, this doesn’t cause a problem.
From there, it’s straightforward to iterate over the appropriate input elements and validate each independently, using the valid() trick covered in the last post.
Handling the enter key
At this point, everything works pretty well, so long as the user clicks on the Button controls to submit the logical forms. Unfortunately, things fall apart if the user triggers form submission by pressing enter in one of the form fields.
One way to fix that would be to handle the form’s onsubmit event, determine if an element flagged with the causesValidation class triggered the submission, and then run through our validation first. That’s perfectly valid, but I avoid that because it tends to clash with other functionality that handles the event; the jQuery form plugin for example.
The alternative that I prefer is to handle a validated field’s onkeydown event. That way, if the element does need to trigger validation, it can do so early, and get out of the way quickly otherwise.
Using jQuery’s cross-browser normalized event object, testing for the enter key is not difficult at all. When handling keyboard related events, one property of that object is keyCode. This property will contain the ASCII character code of the key which triggered the event. In the case of the enter key, that keyCode is 13.
That in mind, this is a first iteration of adding enter key handling to our existing validation code:
// Select any input[type=text] elements within a validation group
// and attach keydown handlers to all of them.
$('.validationGroup :text').keydown(function (evt) {
// Only execute validation if the key pressed was enter.
if (evt.keyCode == 13) {
// Validation code goes here.
}
});
Whether the form is submitted by clicking a button or hitting the enter key within one of our validation groups’ text fields, the appropriate inputs will be validated, error messages displayed if necessary, and submission will only continue if the form is valid.
Refactoring to eliminate duplication
After adding the keydown handler, everything works great, but it’s no good to have that validation code duplicated for both the click and keydown handlers. By passing around a reference to the jQuery event object, we can reuse the same validation code for both event types and make the code much more concise:
$(document).ready(function () {
// Initialize validation on the entire ASP.NET form.
$("#form1").validate({
// This prevents validation from running on every
// form submission by default.
onsubmit: false
});
// Search for controls marked with the causesValidation flag
// that are contained anywhere within elements marked as
// validationGroups, and wire their click event up.
$('.validationGroup .causesValidation').click(ValidateAndSubmit);
// Select any input[type=text] elements within a validation group
// and attach keydown handlers to all of them.
$('.validationGroup :text').keydown(function (evt) {
// Only execute validation if the key pressed was enter.
if (evt.keyCode == 13) {
ValidateAndSubmit(evt);
}
});
});
function ValidateAndSubmit(evt) {
// Ascend from the button that triggered this click event
// until we find a container element flagged with
// .validationGroup and store a reference to that element.
var $group = $(evt.currentTarget).parents('.validationGroup');
var isValid = true;
// Descending from that .validationGroup element, find any input
// elements within it, iterate over them, and run validation on
// each of them.
$group.find(':input').each(function (i, item) {
if (!$(item).valid())
isValid = false;
});
// If any fields failed validation, prevent the button's click
// event from triggering form submission.
if (!isValid)
evt.preventDefault();
}
First, the validation code is refactored into a separate function: Validate.
Since it needs the ability to conditionally call preventDefault in order to stop form submission, the function accepts the event handlers’ jQuery event object as a parameter.
In fact, because $(this) is a reasonable place to begin the parents() traversal for either event that may call the method, very little refactoring is necessary.
The one thing that may seem strange is that the Validate function is being passed as a click handler without any parameters. The reason that this works is because the Validate function is defined with the same signature that jQuery expects. Because of that alignment, Validate will automatically be provided with the same event object that we’ve been using in anonymous callback functions thus far.
Calculated readability
Note that I attached keydown handlers to all of the text inputs within a validation group, regardless of whether or not they are actually validated fields. Similarly, you may have noticed that the click handler finds every input element within its validation group, even if those inputs aren’t marked for validation. This may seem like an oversight, but it’s an intended readability compromise.
You could modify the selector to be more precise, selecting only fields flagged with validation classes (e.g. required, email, number, etc). However, this gets messy when you consider the wide variety of classes that are valid for tagging elements with jQuery validation functionality.
Rather than be precisely specific, I rely on the fact that jQuery validation’s valid() method returns true for elements which are not configured for validation. So, even if we do end up checking the validation status of a few irrelevant input fields, it won’t adversely impact the outcome of the validation process.
There are performance penalties to performing validation on these unnecessary elements, but it is negligible for a reasonably sized form. The ancillary inputs would have to number in the thousands before the penalty were noticeable, at which no one will probably ever successfully complete it anyway!
Conclusion
There are even more enhancements to be had, but I think this brings the solution to a point that it’s useful. With multiple logical forms handled and the perennially pesky enter key tamed, the majority of use cases should be covered.
The most troublesome issue still remaining is that care should be taken to avoid nesting container elements with the validationGroup class on them. Otherwise, the Validate() function will search “too high” and possibly hinge validation on input fields that are not intended. It’s an edge case (fixable if necessary), but something to keep in mind.
Another edge case is that, unlike the ASP.NET Validators, these validation groups can’t overlap. For my own use, this has never been an issue. I’m curious if that’s a real-world problem for any of you.
Finally, an entirely different approach well worth considering is John Rummell’s xVal for Webforms. Using Data Annotations to specify validation rules is gaining a lot of popularity, so it’s worth investigating options like this one. At the minimum, it will help you be more familiar with how validation is handled in ASP.NET MVC.
Hope that helps. Be sure to take a look at the source download to see everything pulled together and one extra usability feature that I didn’t have time to cover.
Source

###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Emulate ASP.NET validation groups with jQuery validation
 |
|
|
|
|
|
|
|

You’ve probably noticed that Jörn Zaefferer’s jQuery validation plugin has been gaining momentum in the ASP.NET community lately. Between Microsoft’s implied endorsement via ASP.NET MVC 2.0 integration and the plugin’s recent inclusion on the Microsoft AJAX CDN, adoption is only increasing. Unfortunately for those who don’t or can’t use ASP.NET MVC yet, using the validation plugin within WebForms applications can be tricky.
Because the WebForms Postback model requires that the entire page be contained within a single form element, form submissions that shouldn’t trigger validation are likely. ASP.NET’s built-in validation controls solve this with ValidationGroups and the CausesValidation property, but that doesn’t help if you’d prefer to use the jQuery validation plugin.
However, there are a couple relatively easy workarounds that make it possible to use the jQuery validation plugin on WebForms pages, without re-architecting the page or its forms. In this post, I’ll show you why the WebForms page structure is a problem, how to make jQuery validation work with it, and an example of implementing those workarounds.
Note: I want to preface this by saying that you should never rely entirely on client-side validation. The jQuery validation plugin can be a great replacement for the client-side part of the ASP.NET Validators, but it is not a complete replacement on its own. Use responsibly!
<form> over function
When it comes to using jQuery validation, the trouble with WebForms is that it requires all of the ASP.NET controls on a page to be contained within a single form element. That doesn’t lead to any problems in simple demos, but things are more complicated when it comes to real-world pages. They often require multiple logical forms on the same page, and that’s where the problems start.
For example, consider the common scenario of having both a login form and a customer information form on the same page. We’ve probably all seen something like this before:
<form id="form1" runat="server">
<fieldset>
<legend>Returning customer? Login here</legend>
<label for="Username">Email:</label>
<asp:TextBox runat="server" ID="Username" />
<label for="Password">Password:</label>
<asp:TextBox runat="server" ID="Password" TextMode="Password" />
<asp:Button runat="server" ID="Login" Text="Login" />
</fieldset>
<fieldset id="BillingInfo">
<legend>New customer? Provide the following</legend>
<label for="FirstName">First Name:</label>
<asp:TextBox runat="server" ID="FirstName" CssClass="required" />
<label for="LastName">Last Name:</label>
<asp:TextBox runat="server" ID="LastName" CssClass="required" />
<label for="Address">Address:</label>
<asp:TextBox runat="server" ID="Address" CssClass="required" />
<label for="City">City:</label>
<asp:TextBox runat="server" ID="City" CssClass="required" />
<label for="State">State:</label>
<asp:TextBox runat="server" ID="State" CssClass="required" />
<label for="Zip">Zip:</label>
<asp:TextBox runat="server" ID="Zip" CssClass="required" />
<asp:Button runat="server" ID="Order" Text="Submit Order" />
</fieldset>
</form>
In most web frameworks, you would divide both logical forms into separate form elements, but WebForms requires both to remain joined within its single form element. This means that clicking either of the Button controls will submit both logical forms together.
Once applied to a form through its default usage, the jQuery validation plugin will attempt to validate all of the elements on that form any time it is submitted. That automation is usually handy, but it means users trying to submit our login form will be denied due to validation failing on the unrelated fields below.

Since using separate form elements containing WebForms controls isn’t realistic, we need to tackle this on the client-side and find a way to make jQuery validation more WebForms-friendly.
Taming jQuery validation
To remedy this problem, we first need to prevent the jQuery validation plugin from automatically triggering on every form submission. The initializer’s onsubmit property allows us to do just that:
$(document).ready(function() {
// Initialize validation on the entire ASP.NET form
$("#form1").validate({
// This prevents validation from running on every
// form submission by default.
onsubmit: false
});
});
That fixes our problem of the login form triggering unwanted validation in the form below, but it creates another issue. Now, neither of the forms will validate when submitted.
Taking control with on-demand validation
Instead of relying on the plugin to automatically validate form submissions, you may also use a less widely known method for triggering the validation on-demand. When added to a page, one of the new methods that jQuery validation exposes on the jQuery object is valid().
When valid() is called on the jQuery object returned from selecting a “validated” form element, it will trigger validation on every field within the form and return a Boolean value indicating whether or not the form is valid.
$(document).ready(function() {
$("#form1").validate({
onsubmit: false
});
$("#Order").click(function(evt) {
// Validate the form and retain the result.
var isValid = $("#form1").valid();
// If the form didn't validate, prevent the
// form submission.
if (!isValid)
evt.preventDefault();
});
});
At first glance, this code might look incomplete to you. We care about more than just preventing form submissions when the form fails validation; we must also indicate the validation errors to the user.
Fortunately, the valid() method has the very useful side effect of displaying the plugin’s configured validation errors for any fields it finds to fail validation.
From the user’s perspective, this implementation is the same as the original one using the default usage. This method just happens to also have the added benefit of actually allowing returning users to log in.
To be continued…
This solution is a good start, but has (at least) two flaws.
First, it doesn’t handle keyboard triggered form submissions. What happens if the user hits the enter key in one of the TextBoxes?
Second, what if we want to also validate the login form? If validation rules are added to that form’s fields, we’ll have exactly the opposite problem as what we started with. Valid submissions in the lower form will be prevented by validation failures on the upper form.
For solutions to both of those problems, be sure to read my followup post: Emulate ASP.NET WebForms validation groups with jQuery validation.
Download the Source

###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Using jQuery validation with ASP.NET WebForms
 |
|
|
|
|
|
|
|
By now, you probably already know that Google hosts jQuery on its AJAX APIs CDN, free of charge. As I’ve discussed here in the past, I’m a big fan of using their CDN to achieve decreased latency, increased parallelism, and better caching.
If you’ve explored the AJAX APIs documentation a bit, you may know that jQuery UI is also hosted on Google’s CDN. Unfortunately, since jQuery UI plugins depend on a ThemeRoller theme, using a CDN for jQuery UI isn’t as easy as with jQuery itself.
Or, is it?
My <head> is in the cloud
While poking around a couple months ago, I stumbled upon something that I’ve found extremely useful: An entire jQuery UI theme hosted on Google’s CDN!
Not only is the theme’s CSS stylesheet there, but all 14 of the theme’s images are hosted in the correct relative location too. That means you can apply the entire theme to a page with a single CSS reference and no local files.
Even better, while JavaScript and CSS includes are unable to take full advantage of the increased parallelism a CDN offers, the theme’s images do. This makes loading the theme from Google’s CDN particularly effective.
Using it
Using this on your own pages couldn’t be easier. There are no files to download, no paths to worry about, and no configuration is required. Just a reference to jQuery, jQuery UI, and the ThemeRoller theme you want to use will is all you need.
For example, if you wanted to build a quick demo of the jQuery UI Tabs plugin, use these references in the head of your page:
<!DOCTYPE html>
<html>
<head>
<!-- To avoid horizontal scrolling in this code listing. -->
<base href="http://ajax.googleapis.com/" />
<!-- Reference the theme's stylesheet on the Google CDN -->
<link href="/ajax/libs/jqueryui/1.7.2/themes/start/jquery-ui.css"
type="text/css" rel="Stylesheet" />
<!-- Reference jQuery and jQuery UI from the CDN. Remember
that the order of these two elements is important -->
<script src="/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<!-- Initialize the tabs when the document is ready -->
<script type="text/javascript">
$(document).ready(function() {
// See the jQuery UI Tabs documentation for
// more information about how this works.
$('#tabs').tabs();
});
</script>
</head>
Note: You shouldn’t use the <base> tag like this in your pages. It affects all links on the page, not just those in the <head>. I’m just using it here to avoid horizontal scrolling (the bane of my existence when posting code here).
Then, just a bit of corresponding markup in the body of the document (see the jQuery UI Tabs documentation for specifics):
<body>
<div id="tabs">
<ul>
<li><a href="#tab-1">Tab 1</a></li>
<li><a href="#tab-2">Tab 2</a></li>
<li><a href="#tab-3">Tab 3</a></li>
</ul>
<div id="tab-1">
<p>These tabs were created with JavaScript, CSS, and
images hosted on Google's AJAX APIs CDN.</p>
<p>Thanks, Google!</p>
</div>
<div id="tab-2">
<!-- Tab 2's content goes here. -->
</div>
<div id="tab-3">
<!-- Tab 3's content goes here. -->
</div>
</div>
</body>
</html>
That HTML (without a single file or image hosted locally) results in this:

Don’t like the theme in my example? Don’t worry, because all 24 of the standard ThemeRoller presets are also hosted on the CDN. See the end of this post for a full listing.
Nothing’s perfect
There are a couple of potential issues when using these CDN hosted themes.
First, these themes aren’t minified. Minification shaves about 20% off the size of an average ThemeRoller theme’s CSS, which is definitely worthwhile. Hopefully, minified versions will be available at some point (assuming I didn’t miss ones that may already be hiding there somewhere). In the meantime, Google does properly gzip compress them though, which makes the difference less significant.
Second, if you normally customize ThemeRoller’s CSS or images manually, this probably isn’t for you. Lacking control over the base CSS style is something that you can work around, but isn’t worth the complexity and extra HTTP requests.
However, you can still reference the CDN’s images from custom CSS, by using absolute paths.
Conclusion
Overall, this seemingly small feature has been surprisingly useful in my day-to-day development. While it’s technically not very difficult to download and set up local ThemeRoller themes, there’s more friction to it than I care for. Boiling the entire process down to a single CSS reference removes all of that friction.
Even if you don’t like the idea of relying on a CDN hosted theme for production sites, this is great for prototyping. Anything that makes prototyping faster is a big win, because it allows you to try more ideas in the same amount of time.
What do you think? Does this sound useful to you? Are you comfortable leaning on Google’s CDN for your entire jQuery UI theme? Would you use this in production?
Full Theme Listing
The URLs below reference jQuery UI v1.7.2 themes. If 1.7.2 isn’t the latest version at the time that you’re reading this, you should be able to replace 1.7.2 in the URL with the current version and find a current theme hosted on the CDN.
Click any of the thumbnails to view that theme on ThemeRoller.
Click any of the input fields to select the full URL to the theme’s CDN hosted CSS file, ready for copy/pasting into your page.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Do you know about this undocumented Google CDN feature?
 |
|
|
|
|
|
|
|
It was great to see all the positive responses to the screencast I recently recorded with Craig Shoemaker on how to use Firebug’s console to learn jQuery. That being my first screencast, I really appreciate all of your support.
However, you almost unanimously commented that it was too difficult to read the commands typed at the console, and you were right. So, Craig and I re-recorded the entire thing, paying extra attention to the legibility of the end result.
Craig also managed to edit the same content down to 9:59m this time, so you can watch it on YouTube if you prefer:
If the HQ version of the YouTube video still isn’t legible enough for you, Craig also made a full resolution WMV available as well.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Updated: See how I used Firebug to learn jQuery
 |
|
|
|
|
|
|
|

While there’s no question that HTML, CSS, and JavaScript form the foundation of modern web development, achieving fluency hasn’t been easy for everyone. In particular, the transition from stateful development with pixel-precise layout – such as VB6 offered – has proven to be especially difficult. HTTP’s stateless nature and HTML’s relatively imprecise layout present a new, different set of challenges.
WebForms aspired to insulate us from those inconveniences. Promising rapid, drag ‘n drop layout and event-driven programming, WebForms was an attractive choice for anyone struggling with web development closer to the metal. Unfortunately, it has become apparent over the years that the WebForms abstraction, while convenient, can easily cause more problems than it solves.
More recently, Silverlight’s WYSIWYG layout and choice of familiar CLR languages have made it a similarly enticing alternative to HTML, CSS, and JavaScript among some .NET developers, but is history repeating itself? Are we leveraging Silverlight to move the platform forward or is it being used as another crutch?
Specifically, I want you to consider three areas that are negatively impacted by overzealous use of Silverlight: Usability, accessibility, and maintainability.
Usability
The Microsoft Thrive for Developers site (which has some great content) is what originally motivated this post. I’ve been percolating these concerns for some time, but my initial experience there served as a lightening rod for them.
After landing on the page, I was greeted by this progress indicator and watched it load for several seconds:

Expecting something worthy of using Silverlight, I was content to wait on the Silverlight to load. Unfortunately, the entire thing turned out to be nothing more than a simple horizontal accordion:

Even forgiving the excessive load time, these Flash/Silverlight-based horizontal accordions are a plague on usability. If you put something in my browser that looks like links and images, it should behave like links and images!
A partial list of the various usability problems that arise include:
Context Menus – When I right click a button intent on opening a link in a new tab or window, seeing a context menu with a single “Silverlight” option is not a good experience. Eliminating the standard context menu defeats several features that you may not use, but some of your users do.
Similarly, when your site thwarts the gesture plugin I use, you’re only hurting yourself. When I can’t drag a site’s links into background tabs without interrupting what I’m doing, I’m far less likely to view as many pages as I normally would.
Browser History – Just as with WebForms before, fully Silverlight based sites break the browser’s expected history, navigation, and bookmarking features by default. There are workarounds, but it’s uncommon to see them actually used.
Text Field Interop – Because Silverlight TextBox controls are not HTML input elements, they sacrifice a wide range of functionality, from password managers to the ability to drag ‘n drop selected text to and from these fields.
Using these islands of Silverlight reminds me of the usability of WebForms Buttons and LinkButtons used for navigation, which have the same problems. It wasn’t a good idea to break the browser’s basic functionality then and it still isn’t now.
Accessibility
It’s no secret that plugin-based technologies like Silverlight obscure their content in an inaccessible manner. Tempting as it sometimes is to turn a blind eye to this problem, accessibility is something that everyone should care about.
Though Microsoft is taking great steps to mitigate Silverlight’s accessibility issues, by embracing the W3C’s ARIA initiative, ARIA is no panacea. It is a compromise to improve the situation, but not a solution to the fundamental problem. In fact, the W3C’s first recommendation when building an ARIA compliant application is:
Use native markup when possible.
Use the semantic elements that are defined in the host markup language. For example, with HTML or XHTML, it is better to use the native checkbox than to use a div element with role checkbox as these should already be accessible through your browser.
Even if every one of your site’s users are without physical impairment, accessibly designed sites yield a variety of other benefits as byproducts. For example, what do you think a search engine spider will glean from this markup?
<object data="data:application/x-silverlight-2,"
type="application/x-silverlight-2"
style="width: 775px; height: 273px;">
<param name="source" value="xap/ThriveSilverlight.xap"/>
<param name="background" value="transparent" />
<param name="windowless" value="true" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
</object>
Probably not much. At least it might rank well for application/x-silverlight-2.
Now, compare that to the semantic HTML markup that might be used to implement the same functionality with a bit of CSS and JavaScript:
<ul>
<li id="Advance">
<h2>Advance Your Career</h2>
<p>Take control of your career path. We've got industry
experts and developer community leaders to give you a hand.</p>
<a href="Advance/CareerResources">
<img src="GetCareerResources.png"
alt="Get Career Resources" />
</a>
<a href="Advance/TrainingCert">
<img src="GetTrainingResources.png"
alt="Get Training Resources" />
</a>
</li>
<li id="Enhance">
<!-- More content here -->
</li>
<li id="Connect">
<!-- And again -->
</li>
</ul>
The difference speaks for itself.
In the same vein, an application that exposes its content accessibly is one that is resilient to change. The ability to easily screen-scrape HTML sites has led to some of the most interesting and useful applications online.
Where an accessible app out often matures into something of a loosely coupled data source toward its end of life, walled gardens of Java, ActiveX, Flash, and/or Silverlight are too opaque to offer that lasting benefit after they’ve become dated.
(un)Bonus: Mobility
Speaking of accessibility, take a look at this same site on an iPhone, which has arguably the best default mobile browser currently available:

HTML 5, CSS3, and JavaScript are probably the future for several classes of mobile applications. In fact, mobile support can be as easy as dropping in a new view for each device. Something like the (awesome) Chipotle iPhone app could just as easily be a mobile view using jQTouch.
With the growing ubiquity of devices like the iPhone, Palm Pre, and Android-based handsets, catering to mobile browsers is becoming an important consideration. Even if it’s still a minority use case (for now), users gravitate to sites that do work well with their mobile devices in that occasional pinch.
Maintainability
Long-term maintenance is a critical consideration when using plugin-based tools.
Think about all of the decade-old web applications that your business or clients are still keeping alive today. How many of them encapsulate important functionality within ActiveX controls? Probably almost none, and there’s a good reason for that.
These monolithic rectangles rot at a frightening rate. Maintaining plugin-based functionality entails more friction and a less widely available skill set than updating HTML markup, tweaking a CSS stylesheet, or changing a JavaScript include. More often than not, these opaque rectangles simply fall by the wayside over time, and might as well be chunks of the website written in COBOL.

If segregating functionality into plugin-based walled gardens was a good idea, we’d still be using Java applets for rollovers in navigation menus.
Silverlight and WebForms aren’t the problem
To be perfectly clear, I think Silverlight is great.
Given the choice between Flash or Silverlight video, I’ll choose Silverlight every time. The video playback is smoother and Microsoft’s great development tooling tends to encourage feature-rich player applications. Even with HTML 5’s <video> element, browser-native video can’t currently compete with Silverlight.
Given the choice between developing an internal dashboard in Flash or Silverlight, I’ll choose Silverlight every time. The charting controls already available even after Silverlight’s short time on the market are awesome, and only getting better. HTML 5’s <canvas> may eventually become the best solution for this, but it’s going to be years before that’s a feasible reality.
There are plenty of scenarios where I think Silverlight is perfectly valid. Though it might be easy to take it that way, this is not an anti-Silverlight (or Microsoft) post.
In fact, I think WebForms is fine too.
Used responsibly, WebForms is still a useful and productive abstraction – especially with the great improvements coming in ASP.NET 4.0. There are plenty of times when something like Dynamic Data to scaffold an administration interface is a smart choice.
Conclusion
Bottom line? You should use idiomatic HTML, CSS, and JavaScript if they are at all able to accomplish what you’re trying to do. Embrace the platform.
More specifically, not wanting learn JavaScript is not a valid excuse for pretending it isn’t the Lingua Franca of the web. Many even find, to their surprise, that they enjoy JavaScript once it’s paired with a library like jQuery to abstract away the DOM. Using the tools currently available, it’s easier than ever to learn too.
Having keenly watched the ebb and flow of web technologies over the past fifteen years, I’m comfortable predicting that an investment in learning the underlying basics is crucial if you’re serious about developing for the web. Anything used to avoid this fundamental understanding is a crutch, not a tool.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Is Silverlight the new WebForms?
 |
|
|
|
|
|
|
|
Though the version number only inched up 0.0.1 with this release, it brings quite a few new features; most of them in response to your requests. I can’t include every request, but I will continue to improve the control based on your feedback, so keep them coming.
Changes in v4.1.5 include:
- Updated the base Highslide JS library to v4.1.5.
- Updated the embedded CSS to the latest version bundled with Highslide JS. This fixes the issue with the transparent/blank bar during enlargement if a caption is set.
- A few internal improvements that should make it work more reliably in some situations.
HighslideManager specific changes:
- Added: Support for onmouseover triggering, through a new property called ExpandEvent. Options are Click and MouseOver.
- Added: CenterEnlargements. When true, enlargements will be centered in the browser instead of centered over the thumbnail.
- Added: MarginTop, MarginLeft, MarginBottom, and MarginRight, which mirror the functionality of Highslide’s similarly named settings. For more information, see the documentation for hs.marginLeft.
- Added: AnchorPosition. This property allows you to specify which point on the enlargement will be anchored to the thumbnail. See hs.anchor for more information.
- Added: ShowFullExpandButton. When the full size image is too large to display in the available browser viewport, an enlargement icon normally displays in the bottom right corner. Setting this property to false will cause that icon to have an opacity of 0, effectively hiding it.
HighslideImage specific changes:
- Added: Disabled property. When set to true, no Highslide functionality will be attached to the image. Good for imperatively disabling thumbnails from code-behind.
As always, the control is freely available on the Highslide JS .NET project page.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Highslide JS .NET v4.1.5
 |
|
|
|
|
|
|
|
UPDATE: We’ve recorded a higher quality version of this screencast.
When I hear that someone’s having trouble learning JavaScript or jQuery, my first suggestion to them is always the same: install Firebug and experiment at the console. Whether you’re an experienced JavaScript developer or haven’t written a single line of client-side code, the interactive nature of a command-line is one of the fastest ways to learn.
To demonstrate just how effective Firebug’s console can be, Craig Shoemaker and I recorded a short screencast on the topic. If you’re not taking advantage of this technique, be sure to take a minute (well, 16) and check it out:
http://polymorphicpodcast.com/podcast/video/firebug-and-jquery/
http://encosia.com/2009/09/21/updated-see-how-i-used-firebug-to-learn-jquery/
Question: Would you like to see more screencasts similar to this one?
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
See how I used Firebug to learn jQuery
 |
|
|
|
|
|
|
|
If you’ve been reading long, you might remember that I’ve been a fan of ASP.NET AJAX in Action since the original was published. By avoiding heavy reliance on drag ‘n drop methodologies, the Manning book leaves readers with a deeper understanding of the framework.
Without understanding the underlying mechanisms well, developing successful solutions is as much a function of luck as it is skill; especially when it comes to debugging and maintenance. So, I think a comprehensive book like this is absolutely essential.
Now with more Encosia
Already being a fan of the book, you can probably imagine my response when I got an email from Alessandro asking if I’d like to participate in the Second Edition. It was certainly the easiest decision I made that day, to say the least. I’ll be helping add new examples, writing about ASP.NET AJAX 4.0’s new features, and discussion about automating things like script compression.
Though the book is still several months away from completion, three chapters are already available via the Manning Early Access Program (MEAP) for pre-orders. In fact, one chapter of the book is freely available, so be sure to check it out.
For a full ToC, the MEAP, and more information about the book, head over to the ASP.NET AJAX in Action, Second Edition page on Manning’s site.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Get early access to ASP.NET AJAX in Action, Second Edition
 |
|
|
|
|
|
|
|
As jQuery’s popularity in the .NET community has risen over the past year, one recurring theme I’ve seen is the desire to refactor away the details of using it to call ASP.NET AJAX services. Whether through helper function or specialized jQuery plugin, I’ve seen numerous methods proposed and/or in use.
Personally, the syntax never bothered me. The contentType parameter is ugly, but I have a Visual Studio code snippet for the $.ajax call and rarely think about it.
That came to an end earlier this year, when I started using dataFilter. I needed to isolate my code from the “.d” issue, and wanted to take advantage of browser-native JSON parsing in Firefox 3.5 and IE8, which required a bulky dataFilter.
Repeating that entire callback function in every $.ajax call was not acceptable. So, I was happy to learn that jQuery provides an excellent solution for consolidating settings to be used in multiple instances of $.ajax.
In this post, I’ll show you how to use that consolidation feature, and exactly how I am now using that to more simply call ASP.NET AJAX services with jQuery.
Configuring $.ajax’s default settings
Rather than wrapping the $.ajax call in a plugin or helper function, jQuery provides a built-in solution that I think is a better alternative: $.ajaxSetup.
$.ajaxSetup accepts an array of settings that allows you to supply defaults for any of the parameters that you would set in an $.ajax call. Settings like contentType, type, and dataFilter are all fair game, for example.
Using this function, it’s easy to set jQuery’s $.ajax defaults to match the refined settings that we worked out together last year:
$.ajaxSetup({
type: "POST",
contentType: "application/json; charset=utf-8",
data: "{}"
});
Because parameters to $.ajax override these defaults, presetting “data” to an empty JSON string is safe. Any $.ajax call that does specify a data parameter will function as expected, since the default will be ignored.
The particular issue caused by forgetting the empty data parameter can be difficult to track down, and only shows up after you’ve deployed your application to IIS. So, having the default as a safety net is recommended.
Adding JSON parsing improvements
Because $.ajaxSetup also supports setting a dataFilter, adding the “.d” isolation and browser-native JSON parsing from my last two posts is easy:
$.ajaxSetup({
type: "POST",
contentType: "application/json; charset=utf-8",
data: "{}",
dataFilter: function(data) {
var msg;
if (typeof (JSON) !== 'undefined' &&
typeof (JSON.parse) === 'function')
msg = JSON.parse(data);
else
msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
}
});
This dataFilter processing is actually what pushed me to start using $.ajaxSetup in all of my own projects. It was one thing to accept multiple contentType and method declarations, but repeating the dataFilter for every $.ajax call was more than I could handle.
Putting it to work
With the ASP.NET AJAX defaults set in $.ajaxSetup, all that’s required to call a “ScriptService” or page method is the URL and a success callback:
$.ajax({
url: "HelloWorld.asmx/Hello",
success: function(msg) {
console.log(msg);
}
});
In fact, even the success callback is optional. For example, if you were periodically pinging a “heartbeat” service to keep the user’s session alive, $.ajax would only need the service’s URI.
This more concise syntax makes your service calls far more readable, especially for developers who aren’t familiar with the content-type required by ASP.NET AJAX.
Caution: Sometimes it works too well
While this is a handy way to simplify calls to ASP.NET AJAX services, do understand that $.ajaxSetup applies to all of jQuery’s AJAX derivatives. Setting the default HTTP method and content-type may also impact code and plugins that use jQuery’s built-in communication functionality (e.g. $.getJSON, $.post, etc).
For example, I often use jTemplates as a client-side templating solution. Because its processTemplateURL routine relies on $.ajax to retrieve remote template files, setting the ASP.NET AJAX content-type and POST method in $.ajaxSetup breaks that functionality of jTemplates.
Fixing that problem wasn’t difficult, but it also wasn’t immediately obvious what had caused the issue in the first place. In my experience using this technique, the undesirable side effects are rare enough that it’s not a serious concern, but do be aware of the potential.
Conclusion
I’ve been using this in production for several months now, with great results. Users have noticed the increased speed that came with browser-native JSON parsing, the “.d” isolation has reduced regression errors due to some code we run on both 2.0 and 3.5 servers, and it requires less effort on my part to do all that.
What do you think? Is this helpful?
Would a Visual Studio template with this rolled in be something you would use?
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Simplify calling ASP.NET AJAX services from jQuery
 |
|
|
|
|
|
|
|
When you’re working with JSON, performance and security are often opposing, yet equally important concerns. One of these areas of contention is handling the JSON strings returned by a server. Most JavaScript libraries do a great job of abstracting away the details, but the underlying process has long been a frustrating exercise in compromise.
On one hand, eval() is the fastest widely available method, but it is not safe.
On the other hand, textual JSON parsers written in JavaScript may be much safer, but are dramatically slower. In client-side situations, where milliseconds count, such a large performance overhead is typically too prohibitive to accept.
Recently, an exciting new alternative has emerged: browser-native JSON parsing. Integrating JSON parsing as part of the browser’s implementation of JavaScript allows for using the more secure parsing method, and even provides performance faster than eval() offers.
To take advantage of that, this post will show you how to detect whether or not a browser supports native JSON parsing, and how to force jQuery to use browser-native parsing in its $.ajax calls when it is available.
Native JSON parsing in the browser
Previously known as ECMAScript 3.1, ECMAScript “Fifth Edition” (the specification that JavaScript implements) formally codifies a native JSON parsing feature. The spec’s API exactly mirrors that of Crockford’s implementations of JSON.parse and JSON.stringify in json2.js, easing the transition to browser-native functionality.
This native JSON parsing brings marked improvements in terms of both security and performance. Not only does the native routine use textual parsing to avoid the risk of executing malicious code embedded within JSON, but it is also fast.
At the time of this writing, three major browsers already include support for native JSON parsing: IE8, Firefox 3.5, and Chrome 3.
Safari 4 does not currently support the standard, but its underlying engine (WebKit) has recently implemented it. Hopefully the feature will make its way to Safari soon.
Detecting native JSON support
Determining whether or not native JSON parsing is available within a given browser is the first problem we need to solve. To do this, we ultimately need to know if the JSON.parse function is defined.
We can’t test for JSON.parse directly because attempting to reference it will throw a JavaScript error if the underlying JSON object doesn’t exist. So, first we need to inspect the type of that underlying object itself:
if (typeof(JSON) === 'object') {
// native JSON may be available.
}
If we find that the JSON object does exist, it’s likely that native JSON parsing is available. However, it’s a best to double check the JSON.parse function as well:
if (typeof(JSON.parse) === 'function') {
// native JSON parsing is available.
}
Because JavaScript performs short-circuit evaluation, it’s safe to clean this up by combining both tests in a single conditional, as long as they’re in this order:
if (typeof(JSON) === 'object' &&
typeof(JSON.parse) === 'function') {
// Native JSON parsing is available.
}
Curious whether your browser supports native JSON parsing? Using the JavaScript above, I have determined that:
Extending jQuery to use native JSON parsing
In my previous post, I demonstrated how to use jQuery’s dataFilter to transform a JSON response before it is returned to the $.ajax() success handler. In the process, we also preempted jQuery’s default method for deserializing JSON data.
The focus at that time was implementing the same method for JSON parsing that jQuery uses by default, so eval() was still used. However, we can also use the same dataFilter mechanism to force browser-native JSON parsing instead.
Using our JSON parsing detection code and a dataFilter callback, upgrading jQuery to use browser-native parsing is simple:
$.ajax({
// Your usual $.ajax() URL, data, dataType, etc.
dataFilter: function(data) {
if (typeof (JSON) !== 'undefined' &&
typeof (JSON.parse) === 'function')
return JSON.parse(data);
else
return eval('(' + data + ')');
}
});
Because jQuery only attempts to deserialize JSON responses if their type is string, and because the dataFilter callback executes before jQuery would normally perform that deserialization, this technique preempts jQuery’s JSON evaluation completely. In the worst case, it will simply revert back to the same eval() method that jQuery internally uses by default anyway.
Note: It’s important to keep in mind that the dataFilter will run regardless of what type is actually returned from the server. You should only use this when you’re sure that you’re receiving a JSON string.
Conclusion
If you’ve been paying close attention to jQuery’s ongoing development, you may already know that jQuery 1.3.3 will provide functionality very similar to what I’ve shown you. I decided to go ahead and write this post anyway for a few reasons:
- You can use this today, without waiting for jQuery 1.3.3.
- You can use this in previous versions of jQuery, if upgrading isn’t feasible for you (as is often the case with plugins dependent on older versions).
- If you use my technique for isolating your code from ASP.NET AJAX’s “.d”, you will still need a method for deserializing JSON in the dataFilter.
Speaking of that last point, if you’re using jQuery with ASP.NET AJAX services, be sure to watch out for the next post in this (accidental) series. There is at least one more productive step left in improving this workflow that I have been using in my projects and want to share with you soon.
###
Originally posted at Encosia. If you're reading this elsewhere, come on over and see the original.
Improving jQuery’s JSON performance and security
 |
|
|
|