Knoxville, TN

The Value of Cross-Training

November 3, 2008

While my job focuses on ASP.NET development, I still find myself going back to Python and SnakeSkin for personal web development projects. There’s really two reasons for this. One, I’ve got a pretty nice Linux virtual server hosting account through OpenHosting, so hosting on Apache gives me a lot of freedom. Two, I like the fact that it’s a bit lower-level than ASP.NET (so I’m a little closer to the HTML code) and not as opinionated as an MVC framework like Rails or CakePHP. Three, real men code in vi from the command line.

One of the great strengths of SnakeSkin/Albatross is its handling of form and session state. It’s roughly equivalent to ASP.NET’s ViewState. However, this makes AJAX work a little tricky. When a form is submitted, the posted fields are validated against the original structure of the form on the page; if they don’t match, SnakeSkin throws an exception. Great for keeping spammers out of your contact forms–but not so hot for changing page structure on the fly. And for years, I’ve sort of had to deal with this limitation. Usually, my workaround was to use a separate controller that returned XML data, which I then used to update the page through JavaScript. Fine for small things (and certainly less bandwidth-intensive), but not convenient.

I could go into the complexity of the problem even more, but it boils down to this: you can’t easily update one portion of the page directly. It’s all-or-nothing.

I eventually hit upon half of the solution to the problem a few months ago. If I updated an entire <form> tag in its entirety using prototype’s Ajax.Updater, then the form data would remain intact, and wouldn’t break when I submitted it again. But this was a very limiting solution. If you used multiple <form> tags on a page, then their session state (stored in hidden fields) would get out of sync as you updated each one individually. So, the only way to really make this solution work was to include only one <form> tag on the page. And if you’re doing that, you might as well not use AJAX at all.

It took some time, but the solution finally hit me. It was during Wally McClure‘s ASP.NET AJAX presentation at ETNUG. I had a pretty good idea of what was going on behind the scenes with ASP.NET AJAX, but I’d never really thought about it too much up to that point–the details were safely hidden from me in the Microsoft library, so there was no point in delving into the complexity.

But part of Wally’s presentation was to open up Fiddler and show the actual text of an ASP.NET AJAX response. The response contained the HTML code to be inserted into each UpdatePanel–which was pretty much what I expected. But it also included the updated ViewState as a separate field in the response. And that’s when it clicked.

All I had to do was modify SnakeSkin to spit out both the session state and the HTML response as part of an AJAX call. Then, when the response came in, I would iterate through the <input> tags on the page, and replace the contents of each hidden session state field. This didn’t require a lot of work on the back end (surprisingly, as I’d imagined the code to generate session state was hidden deep within the bowels of SnakeSkin), and only some minor tweaks on the front-end code I’d been using for AJAX.

So, last night, I actually got two-panel demo working. It’s obviously nowhere near as complicated as ASP.NET AJAX’s UpdatePanel–modifying my SnakeSkin page class to support updating multiple sections of the page in one call would just overcomplicate it at this point. But it is a somewhat elegant solution to the problem–that is to say, it’s encapsulated enough that the details of “how” are nearly invisible when you’re creating a page class.

I’ll post some samples if anyone’s interested, but SnakeSkin (and probably Albatross, the project it forked) is so obscure this doesn’t really matter to anyone but me.

The point is, I found it interesting that I solved a problem in one framework just by looking at another. I didn’t copy the solution directly, but it gave me a new way of looking at the problem. So, while you shouldn’t learn every framework, language, and platform out there, it helps to know more than one.

This is especially true in web development, because in a sense, web frameworks don’t matter. Every web application–every HTML-based application that is, since Flash and Silverlight aren’t constrained by the same limitations–is basically working with the same set of inputs, outputs, and limitations. From the user’s perspective, what you can do with one, you can do with any other framework, whether you’re using PHP or ASP.NET or Rails or SnakeSkin or Perl. Obviously, that doesn’t mean they’re all equally suited to every task. The value in the framework is on the back end–maintainability, productivity, data, and support. So as different as they are, all web frameworks can’t be that different in their fundamentals, which means it’s easier to compare, contrast, and borrow concepts in the web arena than it is on the desktop or server.