11 April 2011

IIS6 to IIS7 - Catching Ajax errors

The way Ajax errors are sent to the browser has changed between IIS6 and IIS7. Errors used to be sent automatically and you could parse the XML on the client. Now, the developer is required to do a little more work because IIS traps the error and stops code execution before reaching the end of the method.
For example, the Ext JS Ajax call takes an object with 5 parameters: method, url, params, success and failure. The last parameter is a callback function that is executed if the server sends back a failure.
The good news is that you have to make a small change to the server-side code (only). Another piece of good news is that the code is generic - the snippet will work with most web methods.
To make it work, create a try... block around the code that may throw an error. (This example is written in C#.) Next, add the following catch block:

catch (Exception e) {
HttpResponse Response = HttpContext.Current.Response;
Response.StatusCode = 500;
Response.Write(e.Message);
HttpContext.Current.ApplicationInstance.CompleteRequest();
Response.End();
}

The code above intercepts the error and returns it to the client. If you already had Ajax code listening for failure, you will not have to change the client side at all.

Note: Special thanks to this blog post by Rick Strahl.

28 March 2011

Ext JS - Mixed Collection Extension

At the top of my wish list for Ext JS is some recursive container search logic. There are times when you need to access a control on a form and can get it via a search term.

 In this case, I wanted to look for the control with a tab index of one greater than the current control. Ext.getCmp would make one control dependent on another.  This logic enables me to find the next control in the container by searching for by property for the next largest tabIndex property.

This extension will recursively search an Ext JS (v 2.x) mixed collection for the first object that has the property you are looking for.  The new method is called 'findByProperty'.


/* Extends the mixed collection object and recursively finds an object */

Ext.override(Ext.util.MixedCollection, {

    findByProperty: function (property, value, defaultValue) {

        var obj = defaultValue,

            notFound = true,

            find = function (itm, idx, len) {

                if (itm.items) {
                    this.items.each(find);
                }

                if (itm[property] && itm[property] === value) {
                    obj = itm;
                    notFound = false;
                }

                return notFound;
            };

        this.each(find);

        return obj;
    }
});



Where:
  • property is the string property you are looking for
  • value is the property value 
  • defaultValue is the optional value to be returned if nothing is found

21 March 2011

Ext JS: relayEvents

I have found that the relayEvents method in Ext JS (2.x) is one of the most useful and code-saving techniques one can use.  The purpose of the method is to allow one object to listen to the custom events of another object.

I have found that the documentation is not that good, which can make somewhat RelayEvents hard to use.  Here is my shorthand to make is easy:


listener.relayEvents(broadcaster, ['custom event a', 'custom event b']);

Where:

  • listener: The object listening for events.  Register the array events in the listeners collection of the object
  • broadcaster: The object firing the events.  To fire the event use the fireEvent('custom event a') method within the broadcaster to fire the event

10 March 2011

Override setValue in Ext JS

I am working with Ext JS 2.x and have the need to format numeric values, such as percentages and comma delimited values.

The best way I know to format the numbers is to override the setValue function of the field. My original plan was to put the formatting in the 'change' event, but calling the setValue in the code does not call this event.

The way to override setValue method is easy, but not obvious. The directions are as follows:


[Namespace].form.[FieldName] = Ext.extend(Ext.form.Field {

    constructor: function (config) {

        /// constructor logic here
        [Namespace].form.[FieldName].superclass.constructor.apply(this, arguments);

    },

    setValue: function (val) {

        /// format logic here for val argument
        return [Namespace].form.[FieldName].superclass.SetValue.call(this, val);

    }

});

28 February 2011

Fixing IIS Error 401.2 - Unauthorized Access

I have developed several applications in Ext JS and recently noticed that all my server calls for a grid made two calls to the server. The first call was a fail, but the second call succeeded. This happens so quickly that the user is not even aware of the issue, but I wanted to track it down anyway.

I examined the HTTP traffic using Fiddler, and found this error in the header of the failed call:


You are not authorized to view this page
You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to accept.
---

Please try the following:

  • Contact the Web site administrator if you believe you should be able to view this directory or page.
  • Click the Refresh button to try again with different credentials.
HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration.
Internet Information Services (IIS)

---

Technical Information (for support personnel)

  • Go to Microsoft Product Support Services and perform a title search for the words HTTP and 401.
  • Open IIS Help, which is accessible in IIS Manager (inetmgr),
    and search for topics titled About Security, Authentication, and About Custom Error Messages.


This problem was happening in IIS6 on Win2K3, but I actually observed it happening on II7 on Win2K8 R2. I found a clue on this website, which recommended changing the order of IIS's method for authentication. Unfortunately for me, this post talked about a UI fix that does not appear to be valid for my version of IIS.

Changing the order of authentication is the answer however, although it needs to be done directly in the ApplicationHost.config file. The fix for this issue is as follows:
  1. Find the ApplicationHost.config file in C:\Windows\System32\inetserv\config.
  2. Copy file to new folder.
  3. Open config file in Notepad. Search for NTLM. You will find it in the windowsAuthentication/providers section of the file. The value "Negotiate" will be listed ABOVE NTLM
  4. Copy the entire XML line so that NTLM is the first on the list of providers.
  5. Restart the World Wide Web Publishing service. Once that is done, the issue goes away.