I CAN HAS CODE?!?
Jun
17
Posted in Code Quickie by Michael at 00:17
Tags: , Comments: Comments Off

When you are using any type of "respond to" functionality that is dependant on the Accept header in order to determine how to respond, it is important that any request you make against your application sends the appropriate headers.  This is a pretty simple thing to do when you are making your own AJAX requests, but not always that simple when using library components, such as the JsonStore, provided by ExtJS.  Below, I extend the built-in HttpProxy and TreeLoader to send the appropriate headers for the request.  These extensions are done in place and require no additional code … though, a word of warning, these extensions may break with future versions of the ExtJS framework.  The code below was tested with the RC1 release of ExtJS 3.0.

Ext.override(Ext.data.HttpProxy, {
    request: function(action, rs, params, reader, callback, scope, options) {
        if (this.conn && reader) 
        {
            this.conn.headers = this.conn.headers || {};
            
            if (this.conn.headers.hasOwnProperty('Accept') == false)
            {
                if (reader instanceof Ext.data.JsonReader) 
                    this.conn.headers['Accept'] = 'application/json';
                if (reader instanceof Ext.data.XmlReader) 
                    this.conn.headers['Accept'] = 'application/xml';                            
            }
        } 
        
        Ext.data.HttpProxy.superclass.request.apply(this, arguments);
    }
}); 

Ext.override(Ext.tree.TreeLoader, {
    requestData: function(node, callback){
        if(this.fireEvent("beforeload", this, node, callback) !== false){
            this.transId = Ext.Ajax.request({
                method:this.requestMethod,
                url: this.dataUrl||this.url,
                success: this.handleResponse,
                headers: {'Accept': 'application/json'},
                failure: this.handleFailure,
                scope: this,
                argument: {callback: callback, node: node},
                params: this.getParams(node)
            });
        }else{
            // if the load is cancelled, make sure we notify
            // the node that we are done
            if(typeof callback == "function"){
                callback();
            }
        }
    }
});

There’s not too much to this code.  In our extending of the HttpProxy we override the request method which is only defined in the HttpProxy’s base class (and consequently inherited).  In it, we check to see if there is a conn object as well as a reader and if there is, we check to see if an Accept has already been defined (just in case) and then we set the appropriate Accept header based on the type of reader that is being used.

For the TreeLoader extension, it’s not quite as simple.  Since TreeLoader directly extends from Observable there’s no method we can easily override without overwriting, so for this one, we have to copy the functionality from the TreeLoader implementation itself.  In doing so, we only have to add a headers property to the options for the AJAX request and we’re all set.

May
20
Posted in Code Quickie by Michael at 00:40
Tags: , , Comments: Comments Off

So, yesterday I decided to play around with Adobe AIR, which I’m not familiar with, in conjunction with Ext JS, which I am familiar with.  Overall, if you are familiar with Ext JS on the web, you’re familiar with it in Adobe AIR … except for a number of unique issues due to Adobe AIR’s default sandbox, mostly revolving around the sandbox and what you can and can’t do in it.  Well, I ran into an issue tonight where I needed to use a JsonReader and use Record mappings with dot notation (i.e. binding a field to a child object in the JSON data).  My guess is that, as is the case with eval, new Function(…), which is what the default implementation of getJsonAccessor uses, is blocked by the sandbox.  I fixed it by extending the default JsonReader and providing a new implementation of getJsonAccessor using some code I created a while back for form binding in JavaScript.

JsonReader = Ext.extend(Ext.data.JsonReader, {
    exprToPath: function(expr) {
        var parts = expr.split(".");
        var path = [];
        Ext.each(parts, function(item, index, list) {
            var match = item.match(/([a-zA-Z0-9_]+)\[([^\]]+)\]/);
            if (match)
            {
                path.push(match[1]);
                if (/^\d+$/.test(match[2]))
                    path.push(parseInt(match[2]));
                else
                    path.push(match[2]);
            }
            else
            {
                path.push(item);
            }
        });
        return path;
    },  

    getDataValue: function(o, path) {
        var current = o;
        var rPath = path.slice().reverse();
        while (current && rPath.length > 0)
        {
            var key = rPath.pop();
            if (typeof current[key] !== 'undefined') current = current[key]; else return null;
        }

        return current;
    },

    getJsonAccessor: function(expr) {
        var self = this;
        var path = this.exprToPath(expr);
        return function(obj) {
            return self.getDataValue(obj, path);
        };
    }
});

It’s probably a bit of overkill for what is needed, but it does work well.

May
18
Posted in ASP.NET MVC by Michael at 00:08
Tags: , , , Comments: 3 Comments

In Ruby on Rails (RoR) there is a method on the controller class called respond_to which, simply put, allows one to easily tailor the response format based on the requested mime type format (through the Accept header or as an extension on the URL) of the request.  There are many reasons why you would to do this, but one of the main ones, in my mind, is that you want to have your controllers be able to work with ‘service’ type calls instead of only requests for pages.  The same controller and action could be used to serve up HTML when a normal request comes through, but when a JSON request (i.e. application/json) comes through, instead of using the standard view and layout, only valid JSON data would be returned.

Now there are a number of ways to implement this functionality but I find the RoR method to be quite clean and succinct, and because of that, when I needed to do something similar with ASP.NET MVC, I modeled my approach after RoR’s.  So, without further ado, let’s jump into the code shall we?

I started with a very simple extension method for the HttpRequestBase class that simply checks to see if one or more strings are in the HTTP Accept header.

public static class HttpRequestBaseExtensions
{
    public static bool CanAccept(this HttpRequestBase request, string[] types, bool exact)
    {
        return Array.Exists(
            request.AcceptTypes, 
            a => (a == "*/*" && exact == false) || Array.Exists(
                types, 
                t => t.Equals(a, StringComparison.OrdinalIgnoreCase)
            )
        );
    }
}

Now, there a number of ways to optimize this, but the above is very strait forward and simple.  We iterate over the values in the Accept header, if the header can accept anything, i.e. ‘*/*’, and we don’t need an exact match, we are done and the request can accept the supplied types.  Otherwise, we look over our supplied types, for a matching one.  Easy. 

Since we can now easily check whether or not a given request can accept a supplied type, it’s time to move onto the meat of the code.  Instead of using a strait comparison between the requested and supplied mime types, I opted to use a more extensible approach.  I figure we could make all of our content ‘checks’ predicates so not only could we check for a given mime type, but we could also check to see if the request was an ajax call, or really anything else we want. 

public static class RequestFormat
{        
    public static Predicate<ControllerContext> Html = (c) => 
        c.HttpContext.Request.CanAccept(new [] { "text/html" }, false);
    public static Predicate<ControllerContext> HtmlAsync = (c) => 
        c.HttpContext.Request.CanAccept(new[] { "text/html" }, false) && c.HttpContext.Request.IsAjaxRequest();
    public static Predicate<ControllerContext> Json = (c) => 
        c.HttpContext.Request.CanAccept(new[] { "application/json" }, true);
    public static Predicate<ControllerContext> Xml = (c) => 
        c.HttpContext.Request.CanAccept(new[] { "application/xml" }, true);        
}

I chose to use ControllerContext as the parameter to the predicate instead of HttpRequestBase because by doing so we can access the route values among other things which would let us check for the format in the URL, for example.

public static class RequestExtension
{
    public static Predicate<ControllerContext> Html = (c) => 
        String.IsNullOrEmpty(c.RouteData.Values["format"] as string);
    public static Predicate<ControllerContext> Json = (c) => 
        "json".Equals(c.RouteData.Values["format"] as string, StringComparison.OrdinalIgnoreCase);
    public static Predicate<ControllerContext> Xml = (c) => 
        "xml".Equals(c.RouteData.Values["format"] as string, StringComparison.OrdinalIgnoreCase);
}

Let’s move to the class that does the majority of the work, the RequestFormatResponder.

public class RequestFormatResponder
{
    protected class SupportedFormat
    {
        public Predicate<ControllerContext> Predicate { get; set; }
        public Func<ActionResult> Result { get; set; }
    }

    protected List<SupportedFormat> Supported { get; set; }

    public RequestFormatResponder()
    {
        Supported = new List<SupportedFormat>();
    }

    public Func<ActionResult> this[Predicate<ControllerContext> predicate]
    {
        set { Supported.Add(new SupportedFormat { Predicate = predicate, Result = value }); }
    }

    public ActionResult Respond(ControllerContext context)
    {
        var match = Supported.LastOrDefault(s => s.Predicate(context));

        if (match != null)
            return match.Result();

        return null;
    }

    public Func<ActionResult> Html { set { this[RequestFormat.Html] = value; } }
    public Func<ActionResult> HtmlAsync { set { this[RequestFormat.HtmlAsync] = value; } }
    public Func<ActionResult> Json { set { this[RequestFormat.Json] = value; } }
    public Func<ActionResult> Xml { set { this[RequestFormat.Xml] = value; } }
}  

There’s really not too much to go over.  We have a child class, SupportedFormat, that contains a supplied predicate and function to return an ActionResult, which is the resultant value should a an acceptable match be found.  On top of that, we have a list to store the formats that are acceptable (order is important), we have a couple ways of setting those supported formats, and we have the function that does all of our processing, Respond.  I’ll get to the two ways of setting supported values in a bit, but it is worth noting that the Respond method implies that the order of the supported formats should be least specific to most specific.

Now, we are almost ready to use our nifty new respond_to implementation.  There is only one more thing to do and that is provide our method on the controller.  I prefer to create a controller class which all of my controllers inherit from in an application (called ApplicationController no less … a hold over from my time with RoR) so I’m going to place our very own RespondTo method there.

public class ApplicationController : Controller
{
    protected ActionResult RespondTo(Action<RequestFormatResponder> block)
    {
        var responder = new RequestFormatResponder();

        if (block != null)
            block(responder);

        var result = responder.Respond(ControllerContext);
        if (result != null)
            return result;           

        throw new HttpException(400, "Unable to respond to requested format.");
    }
}

Overall, it’s pretty simple.  We accept a delegate parameter to which we will pass our responder instance.  We create our responder, call the block, and let our responder do its work.  If the result is non null, we return and go about our way, otherwise we through an exception to return an HTTP status code of 400 (bad request) since the request was for a format we don’t support.

It’s now time for the fun part … putting our code to use!  I merely created a basic ASP.NET MVC project for this part.

public class HomeController : ApplicationController
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return RespondTo(format =>
        {
            format.Html = () => View();
            format.Json = () => Json(new { message = "hello world" });              
        });            
    }

    public ActionResult About()
    {
        return RespondTo(format =>
        {
            format[RequestExtension.Html] = () => View();
            format[RequestExtension.Json] = () => Json(new { message = "about" });
        });
    }
}
/* route to support extension based format */
routes.MapRoute(
    "Default-Extension",                                              
    "{controller}/{action}.{format}/{id}",                  
    new { controller = "Home", action = "Index", id = "" }  
);

Bam!  Here you can see we call our RespondTo method and pass in a lambda expression in which we will tell the responder what formats we support.  In the Index action, I’m using the property setters defined at the bottom of our RequestFormatResponder class which, as you can see, look fairly similar to the RoR method.  The only downside is that you have to add all of the formats that you will support to your responder, but in most cases, that won’t be a big deal.  I the About action, instead of using the property setters, we use the index setter.  It’s pretty similar, though not as clean, in my opinion.  However, you don’t need to extend your responder class at all to add more types.  You could even just specify a new predicate right there if you needed to. 

The rest of that code block should be pretty easy to read.  When a request comes in for HTML, we are simply telling it to return our View, and when a request comes in for JSON, we are telling it to return a JSON serialized object.  The reason we have to use the lambda expressions as values instead of the functions themselves is because we don’t want the actual function executed the correct format has been determined.  If we didn’t do this, both View and Json would be executed, and then the correct one to return would be determined. 

Well, there you have it.  Ruby on Rails like respond_to functionality in an ASP.NET MVC world.  We’ve been using this approach in a project at work and, so far, it’s worked out quite well.  I hope you find it just as useful.

May
17
Posted in Life by Michael at 02:14
, Comments: Comments Off

Yes, I just quoted a WoW achievement, and a Grateful Dead song, apparently, but in the span of time since my last post, I do find it oddly fitting, in a good way.  Just what have I been up to you ask?  Well, I’m glad you asked :)   Probably the biggest event was that my wife and I had our first child.  Definitely a life altering an amazing experience that words cannot adequately describe.  In the work sphere, I’ve been taking on a bit more responsibility here and there and have been learning a lot as well.  I’ve become quite well acquainted with Ext JS and jQuery and enjoy working with them both.  Also, I’ve been working a good bit with ASP.NET MVC lately and I’ll definitely say that, overall, I’m impressed with their implementation, though I do still enjoy MonoRail.  On the side, I’ve also been writing an MVC framework for PHP, yes, another one, and it’s been a fun experience.  Look forward to some posts regarding that in the near future … and some on ASP.NET MVC in the immediate future. 

Overall, it’s been a really good 10 months and I’m definitely looking forward to the next 10 months … hopefully with a few more blog posts.

Jul
17
Posted in Annoyances by Michael at 22:44
Tags: , , , Comments: Comments Off

It must just be my luck.  This is the second time in not so many weeks that I’ve ran into an issue with WebForms where something decides that it knows better than me, ignores what I tell it, and goes off on its own merry way.  At least it offers a good opportunity to break out .NET Reflector and do some detective work.

Last time we looked over an issue with the CssTextWriter writing out invalid “background-image” attributes.  This time we are going to be looking over an issue with the GridView and it mis-calculating column span for pager sections when adding cells to the GridView in a very specific manner.

Now, there are several ways to go about adding cells to the GridView.  The most common way, and generally the simplest way, is to add an “empty” column to the Columns collection and doing what you will with it, either with a template or by modifying in OnRowCreated.  This works for most situations, spans correctly, and is the easiest to manage.  Let’s imagine for a second, though, that you cannot do it that way.  Perhaps you want a little more fine grained control over where those cells get added, or perhaps, as it was in my case, you’ve already extended the GridView and have a lot of existing code in consumers of your GridView that rely on an explicit ordering of the cells and spectacularly explode when you add the cells this way.  Now, how do you go about adding the cells?

Before we get into the code of adding the cells, let’s just get a basic extended GridView setup:

public class MyGridView : GridView
{
}
<wfs:MyGridView ID="MyGridView" runat="server" AutoGenerateColumns="false" Width="300" PageSize="4" AllowPaging="true">
    <PagerSettings Mode="NumericFirstLast" Position="TopAndBottom" />
    <PagerStyle BackColor="SteelBlue" ForeColor="White" />
    <HeaderStyle BackColor="Gainsboro" />
    <Columns>
        <asp:BoundField HeaderText="One" DataField="one" />
        <asp:BoundField HeaderText="Two"  DataField="two" />
        <asp:BoundField HeaderText="Three"  DataField="three" />
    </Columns>
</wfs:MyGridView>

Now, the way we are going to add our extra TableCells is by overriding OnRowCreated and adding the cells *after* calling base.OnRowCreated().  By doing the manipulation after calling base, any consumers that manipulate the cells will be working with the un-modified cell list.

base.OnRowCreated(e);
if (e.Row.RowType == DataControlRowType.DataRow ||
    e.Row.RowType == DataControlRowType.Header ||
    e.Row.RowType == DataControlRowType.Footer)
{
    TableCell myCell = new TableCell();
    myCell.Text = "AMG";
    e.Row.Cells.AddAt(0, myCell);
}

Now, if we go and view the site, it looks like this:

original-after-col

Doh!  That’s not quite what we were expecting.  If you go and inspect the HTML you will quickly notice that the “colspan” attribute on the top and bottom pagers is incorrect.  In fact, it’s off by one and is the same as the original number of columns.  Well, so how do we get rid of it.  The way you would expect to get rid of it is to override the InitializePager method of the GridView.  The InitializePager method accepts a parameter for the “colspan”, so it should be easy to just override it, add +1 to the input “colspan” parameter and pass it back to the base, right?

protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource)
{
    columnSpan += 1;

    base.InitializePager(row, columnSpan, pagedDataSource);
}

So, that shouldn’t be too hard. After a quick recompile and going back to the site, you’ll find it looks exactly the same as before. Well, poop! Time to break open the debugger and see if it’s actually being set.

If we set a breakpoint in the OnRowCreated method (and go to a row after the pager is created) you’ll see that the TopPagerRow is does in fact have the correct values.

col-span-after

At least at this point we can reasonably assume it’s not necessarily our fault.  Time to put on our detective hats and break out .NET Reflector; first, though, we need to determine where to look.  I like to do that by sticking breakpoints in at key points and seeing where the values change (or don’t change).  A good place to start is with the Render method.  Simply override it, call the base version, and set a breakpoint on that line.  Now, if you were to do that in this situation, you’ll notice that the ColumnSpan is still correct which means that something in the Render function is killing it.

If you navigate to the GridView’s Render method in .NET Reflector you’ll see the following:

reflector-render

The best way to find these things is to look for anything outside the ordinary and as luck would have it, we don’t have to look very far.  What’s this PrepareControlHeirarchy method and what does it do?

reflector-prepare

Notice the rows I’ve underlined.  The above code looks through the cells in any given row that are of the DataControlFieldCell type, which ours is definitely not, and it increments a variable for each one found that is in a data row.  After looking for where the “num” variable is used, you’ll find the following:

reflector-prepare-2

And there we have it!  That’s the cause of our ColumnSpan being off.  Since our cell was not of the “correct” type, it happily ignored it and did what it thought it should do.  Nice.  Well, at least in this case the PrepareControlHeirarchy method is virtual.  If we override that method and adjust it like so, we should be golden.

protected override void PrepareControlHierarchy()
{
    base.PrepareControlHierarchy();

    if (TopPagerRow != null && TopPagerRow.Cells.Count > 0)
        TopPagerRow.Cells[0].ColumnSpan = 4;
}

I’m only “fixing” the TopPagerRow here with regards to space and to clearly illustrate the fix.  A quick rebuild and run and we are greeted with the following, wonderous, sight:

finished

Which is exactly what we were going for.

I mentioned at the start of this post that this situation is not one that is likely encountered, but it’s always good to know how to dig into the framework and see what’s going on under the covers.  .NET Reflector a very valuable tool to keep in your toolkit.

Jun
19
Posted in Annoyances by Michael at 23:40
Tags: , , , Comments: Comments Off

Sometimes I get annoyed with ASP.NET WebForms … No, make that greatly annoyed and disappointed with web forms.  As I mentioned in my last post, I was recently troubleshooting a 2nd incarnation of the mysterious multiple request syndrome (MMRS for short).  What made this time worse was what ending up being the cause.  In this case the request was being caused by a “url(none)” in a style attribute.  After tracking down the offending component I found something similar to the following example in the code.

Panel inner = new Panel();
inner.ID = "inner";
inner.Style.Add("background-image", "none");

Notice the last line.  Looks correct doesn’t it?  WRONG!  It’s not correct because WebForms Know Better Than You! ™.  When the above is rendered out to the page, it looks like this:

<div id="inner" style="background-image: url(none);"> </div>

Notice anythign wrong?  Yep, right there in the middle … the wonderful “url(none);” and a 2nd request in your browser for the “/none” path.  Well, poo… How did that get in there?  More importantly why did it get in there?  Especially considering the CSS spec specifically allows “none” as a value for the “background-image” property.  In fact the w3 page for the CSS1 (and CSS2) spec says “Value: <url> | none”.

Being the inquisitive sort, there was only one thing that I could do;  Fire up Reflector.NET and go to town.  First order of business was to find the Style property for the Panel control, which ends up being the Style property of the Panel’s base class, WebControl.  It is of type CssStyleCollection … My answer must lie somewhere in there.  The Add method in the CssStyleCollection class isn’t that special and just adds the items to some hash tables.  The Render methods might be interesting however.  After using the Analyzer on those and seeing how they are used we can determine two things.  First, the Render method that takes an HtmlTextWriter merely calls AddStyleAttribute on the writer and adds the CSS properties while the other one takes a CssTextWriter … Wait, what?  That’s a bit different.  It seems to call a WriteAttribute method of the CssTextWriter class.  After making our way to the static WriteAttribute method, we see the following:

if (key != ~HtmlTextWriterStyle.BackgroundColor)
{
    isUrl = attrNameLookupArray[(int) key].isUrl;
}
if (!isUrl)
{
    writer.Write(value);
}
else
{
    WriteUrlAttribute(writer, value);
}

Hmm, what is this “isUrl” and WriteUrlAttribute? Let’s go find out.  A quick Analyze on the “attrNameLookupArray” member shows that it is set in the static constructor so off we go.  In there we see a bunch of RegisterAttribute calls and we see one for the property we set at the beginning of this ordeal, “background-image”.  Digging into the RegisterAttribute method, we see that the last parameter to the function, which in the case of “background-image” is “true”, is the “isUrl” value we are looking for.  So the CssTextWriter considers the “background-image” attribute a URL based attribute … Makes sense, as it is one, so the issue must lie somewhere within WriteUrlAttribute.  Looking at the code for that function:

if (StringUtil.StringStartsWith(url, "url("))
{
    int startIndex = 4;
    int length = url.Length - 4;
    if (StringUtil.StringEndsWith(url, ')'))
    {
        length--;
    }
    str = url.Substring(startIndex, length).Trim();
}
// str is rendered out as "url(" + str + ")" after.

Well, that is unfortunately where are issue lies and there isn’t a damn thing we can do about it.  No special handling of “none”; Just a regurgitation of whatever we set the property to.  That is just too awesome.

Jun
19
Posted in Troubleshooting by Michael at 22:04
Tags: , Comments: 60 Comments

I’ve ran into this issue for the second time today and it was as much of a pain to troubleshoot it as it was the first time around so I figured I’d do a little write-up about it so that others may save themselves a good bit of frustration. 

The first time I encountered the issue, it seemed to happen at random.  I was stepping through some code for the web application I was working on at the time in the debugger and had a breakpoint set that should have only ever been reached once per request and yet this time it was reached twice.  As I was going through some testing, the problem would go away for a time, and then come back, depending on the state of the page. 

Enter the mysterious request… So instead of trying to troubleshoot any further in the debugger I decided it would be good to look at the requests as they happen using FireBug (or Fiddler).  Sure enough, there were two requests anytime I had a certain component visible on the page.  So that narrowed it down further at least in that I knew what component was causing it.  What gave me enough to google on was the fact that the request headers for the 2nd request were different in one very important way, the "Accept" header.  Instead of the usual "text/html" plus friends it was "image/png,image/*" … which indicates it was a request for an image resource.

Armed with that information, I prayed before the google gods and found a couple of posts (seriously, there were only two that I could find) about the issue and one mentioned an empty "src" attribute on an image tag.  That wasn’t the case that time, but it got me thinking … If image tags could do it, what about CSS properties?  Sure enough, that was the problem.  There was one CSS property defined in a style attribute that was "background-image: url();".  Taking care of the offending property made the issue go away and everyone was happy.

Now, there are a number of things that can cause this situation and they are outlined below.  There are also multiple ways that the issue will show itself in a request log. 

An empty "src" attribute on an image tag.

<img src="" />

An emtpy url definition on a CSS property or a url definition with "none"* inside of it.

.test {
background: #ffffff url();
background-image: url('');
background-image: url(none);
}

I’ll be talking more about the last one in a follow up post.

As for how they can show up in a request log:

  • A second request for the same path and query. 
  • A second request for the root path (i.e. the normal request is for "/default.aspx" and the second request is for "/").
  • A second request for the "none" path (i.e. "/none").

In Firefox the second request will usually always have the "Accept: image/png,image/*" header.  Unfortunately that is not always the case with IE.  IE likes to happily send "Accept: */*" along.

Now how do you go about finding these in your code and markup?  Unfortunately that is not always that easy and you may have to resort to using multiple tools.  A good start is the HTML tab in FireBug.  Another good option is "View -> Source -> DOM" option in the IE Developer Toolbar.  Another thing to do is to search your solution for the offending items.  Searching with regular expressions can be a big help there.

I hope this post proves helpful to someone else that encounters the problem.  It was almost as frustrating to find the culprit the second time as it was the first time and I knew what I was looking for … though part of that problem was WebForms working against me, but more on that later.

Jun
17
Posted in Nothing Important by Michael at 00:50
Tags: , Comments: Comments Off

It’s finally here! After much procrastination I have finally gotten around to setting up my blog. My plan is to try and post at least once a week and to keep the topics primarily development and web design related. However, with a title like “I Can Has Code?!?”, I’m sure there will be plenty of room for less “structured” posts.

As for how the name came about… Well, I’m a big fan of lolcats, and while designing the site in photoshop, I typed it in as a placeholder and it just kinda stuck :)