www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Friday, May 29, 2009

I’m in the early stages of writing a web app with a friend who has been somewhat on the periphery of ASP.NET MVC. As in, when someone says “let’s build a web app”, he doesn’t automatically reach for the MVC project template as I typically do. Bear in mind, he’s also not a web forms fan either.

Instead, he has a very specific architecture in mind that has taken me some time to come around to. A simplified version of it is thus: there is one web application for the various HTML files (and yes, they will be HTML only) and another for the “services”. The services one will serve up primarily JSON to the client which will interact with it with a very healthy dose of JavaScript. This is one reason we’ve decided on OpenRasta for the services layer.

I’ve deferred to my friend on some of this because I feel like I have too much emotional investment in MVC these days (as you can tell by my tendency to erroneously drop the ASP.NET part of the name). Suffice it to say he’s led development on some major league websites that have more traffic in an hour than I have cycles in my family tree. So I feel confident in his evaluation skillz. He has a more rounded view of the world, partially because of his experience with these websites and partially because he hasn’t been drinking the kool-aid as much as I have for some of this stuff.

One of those areas where he isn’t tightly coupled is with JavaScript libraries. Me, I’m a jQuery guy. Not because I like it better than the other libraries but because it’s the only library I’ve ever used and it hasn’t caused me any pain. He has only a passing knowledge of a few of them and attacked the problem of which one to choose more objectively.

To that end, we’ve settled on MooTools, at least for the time being. The main technical reason for this is because jQuery is getting too popular and we don’t want to be perceived as jumping on the bandwagon. We feel that if it’s good enough for Microsoft to throw its support behind, then we need to look at something else.

I jest, of course. In fact, our research shows it to be faster than jQuery and I have it on pretty good authority it is well-suited if you plan to have a somewhat complicated object model on the client. During my spike, I did find it to be more verbose than jQuery but not prohibitively so.

Another JavaScript library we’re playing with is Embedded JavaScript, which is a view engine for JavaScript. With it, you can define views like so:

<h2><%= petNameForRack %></h2>
<ul>
<% for( var i = 0; i < guns.length; i++ ) { %>
    <li><%= guns[i] %></li>
<% } %>
</ul>

This would be stored in an external file and you render it with some JavaScript like so:

function renderListOfLovers( )
{
    var jsonRequest = new Request.JSON( {
        url: "http://localhost/Services.Web/Lovers",
        method: "get",
        onSuccess: function( gunRackList ) {
            gunRackList.Racks.each( buildItem );
        } ).send( );
}

function buildItem( item )
{
    target = $("destinationDiv"); 
    var div = new Element( "div" );
    var view = "views/MyListOLovers.ejs";  // Contains the view shown above
    new EJS( {url: view} ).update(div, item);
    div.inject(target);
}

That's mostly from memory so don’t be cuttin’ and pastin’ none. In the first function, we call out to our OpenRasta service which is configured to return a list of gun racks as JSON by default. When that call succeeds, it creates a new DIV, renders the view in it, then injects it into into a target container.

All in all, it’s an interesting way of doing things. It’s nice that JSON has become kind of the de facto standard for passing stuff around with the various frameworks because it would be a pain to have to retrieve the list from OpenRasta in one format, convert it to another to work with MooTools, then another to work with EJS.

All of this pretty much worked out of the box, too. The spike involved very little actual troubleshooting. It was mostly getting used to the syntax (e.g. I would have thought the MooTools inject function would act on the target rather than the item being injected).

I also discovered you can throw an instance of a custom MooTools class into a view as well with no further changes required. Maybe that’s obvious if you are intimately aware of how JavaScript handles classes but my own experience has been limited to: new ActiveXObject(“MSXML2.XMLHttp”);

On the EJS side of things, it also comes with a bunch of view helpers which are analogous to the dumping ground that is HTML extension methods with ASP.NET MVC.

One roadblock I’ve hit is that while you have the power of a full-fledged library at your disposal with MooTools, in the EJS views, you are limited to only what it supports between the angle brackets. But as a wise man said: in the end, it’s just JavaScript so you can make it do what you want anyway.

How this will end up playing out when things get hairy is still anyone’s guess. But the pain-free spike has been pretty encouraging so far.

Kyle the Scriptified

Tuesday, April 07, 2009

I’m going to go out on a limb and posit that a few of you have attempted, and possibly succeeded, at integrating JsUnit into an automated build process. Assuming that is true, you people are off my Christmas card list for not blogging about it in such a way that it is discoverable by Google. (And that includes you, Miller).

The sole exception to this is honorary hillbilly Toby Henderson who provided enough insight in the comments to Jeremy Miller’s post mentioned so disparagingly above. From that, I was able to come up with the following NAnt task (and Jayzus only knows how this is going to look in an RSS reader):

<target name="jsunittests">
  <property name="jsunit.port" value="9123" />
  <property name="jsunit.authority" value="localhost" />
  <property name="jsnuit.vdir" value="AdventuresInPlaid" />

  <property name="jsunit.acceptor.partialurl"
   
value="${jsunit.authority}:${jsunit.port}/jsunit/acceptor" />
  <property name="jsunit.url"
     value="&quot;
http://${jsunit.authority}/${jsunit.vdir}jsunit/testrunner.html?testPage=${jsunit.authority}/${jsunit.vdir}JsUnitTests.aspx&amp;autoRun=true&amp;submitresults=${jsunit.acceptor.partialurl}&quot;" />
  <property name="jsunit.browserFileNames"
     value="&quot;${programfiles.dir}\internet explorer\iexplore.exe,${programfiles.dir}\Mozilla Firefox\firefox.exe&quot;" />
  <property name="jsunit.log" value="logs" />
  <property name="jsunit.resourceBase" value="" />
  <property name="libs" value="" />
  <foreach item="File" property="filename">
    <in>
      <items>
        <include name="app\BookedIn.Web\JsUnit\java\lib\*.jar" />
      </items>
    </in>
    <do>
      <property name="libs" value="${libs}.\lib\${path::get-file-name(filename)};" />
    </do>
  </foreach>
  <property name="libs"
    value="${string::substring(libs, 0, string::get-length(libs) - 1)}" />
  <exec program="java" workingdir="app\BookedIn.web\jsunit\java"
        commandline="-Dport=${jsunit.port} -DbrowserFileNames=${jsunit.browserFileNames} -Durl=${jsunit.url} -DlogsDirectory=${jsunit.log} -classpath &quot;.\bin\jsunit.jar;.\config\;${libs}&quot; junit.textui.TestRunner net.jsunit.StandaloneTest" />
</target>

Assuming that’s copy-and-pastable into your own script, I’ll move on.

The properties almost certainly should be moved outside of this target, of course. I’ve included them all here for convenience. Some of them are machine specific so putting them at the top means you can override them with a local properties file.

The <foreach> loop in the middle was borne out of frustration. It will look through all the .jar files in the JsUnit lib folder and create a semi-colon-delimited list of them. This is then passed into the classpath for the <exec> task which launches the whole thing. My guess is that Toby used an older version of JsUnit because it appears there are a lot more libraries involved now. After about the third or fourth time running the task with a manually-entered list of libraries and having a ClassDefNotFound error come up, I sought out some help to just dump them all in with the <foreach>.

Word of caution: the config folder included in the classpath contains xwork.xml. The part that caused us the greatest trouble was a message “Error loading configuration file xwork.xml”. This was because we were including the path to the xwork.xml file explicitly, rather than the path to just the config folder. It was the Ant file for JsUnit itself that eventually led to our salvation.

So between this and the recent announcement that my wife is pregnant, all is well in Hillbilly House.

Kyle the Expectant

Sunday, September 28, 2008

You know this by now but my university English professor is a mean sucker and would hunt me down if I didn't provide context for this post. Microsoft will be shipping jQuery with ASP.NET MVC and Visual Studio. I imagine there will be lots to Google about this in the coming days but you can start at the source: ScottGu, ScottHa, John Ressig.

I freakin' LOVE this news if for no other reason than I finally have a counter argument to the MVC mainstay complaint "what about my server-side controls?". According to John Ressig's post, Microsoft will be developing controls on top of jQuery. Combine that with the news that Visual Studio will have IntelliSense support for jQuery and you have yourself a happy codin' hillbilly.

My underlying interpretation of this is that Microsoft will provide reasonable alternatives to the stock server-side controls using jQuery instead. Rob Connery has already provided a pretty detailed tutorial on creating a paged grid in MVC, and he didn't even use jQuery.

Oh yeah, and this is a bold new direction for Microsoft and they're welcoming Open Source and the community and blah blah blah. Whatever, as long as I have something else to say besides "yeah, well, you smell" to people unwilling to give up their GridView.

Kyle the Argumentative

Monday, April 21, 2008

More adventures in JSON serialization. I'm tellin' ya, it's like a Saturday morning cartoon, it's so exciting. And I'm afraid that's about as far off topic as I'm going to get with this one because there'll be a lot of code which tends to push posts into the "Sweet Jayzus, ya think I got that kind of attention span?" territory in my RSS reader. I promise I won't try to learn ya too much agin in the near future.

The scenario

I'm serializing to the browser a List<Location>. Location is an abstract class with two implementations: RuralLocation and UrbanLocation. The method I'm using to serialize this collection to JSON is based on Scott Guthrie's post (though updated to use the DataContractJsonSerializer class:

public static string ToJson( this object obj )
{
    var serializer = new DataContractJsonSerializer( obj.GetType( ) );
    var memoryStream = new MemoryStream( );
    serializer.WriteObject( memoryStream, obj );
    string jsonString = Encoding.Default.GetString( memoryStream.ToArray( ) );
    memoryStream.Close( );
    return jsonString;
}

Here's the code to deserialize:

public static T ToObject( this string jsonString )
{
    var serializer = new DataContractJsonSerializer( typeof ( T ) );
    var memoryStream = new MemoryStream( Encoding.Unicode.GetBytes( jsonString ) );
    var newObject = (T)serializer.ReadObject( memoryStream );
    memoryStream.Close( );
    return newObject;
}

The problem (until this morning) was, I couldn't use the code to deserialize. On my page, I was creating JSON objects representing RuralLocation objects and UrbanLocation objects with an AJAX call using this same ToJson method. Here's the MVC action to create an UrbanLocation JSON string:

public void GetUrbanLocationAsJson( string Lot, string Block,
        string Plan, string Address )
{
    var location = new UrbanLocation
    {
        Lot = Lot,
        Block = Block,
        Plan = Plan,
        Address = Address
    };
    Response.ContentType = "application/x-javascript";
    Response.Write( location.ToJson( ) );
}

This returns the following JSON string: {"Lot":"1", "Block":"2", "Plan":"3", "Address":"111 Hoe Down Way"}. And the corresponding method for RuralLocations created something similar.

The issue was that on the client, I had a collection of heterogenous JSON objects with no indication of what type they were. Yes, each one inherited from the same base class but there was no sign of the type when it was serialized. So when I got the JSON string back on the server, I couldn't make a call like Location[] locations = jsonString.ToObject<Location[]>( ) because it would try to create actual Location objects, not the inherited UrbanLocation and RuralLocation objects.

At the time, my solution was to get any solution working so I deserialized old school: by parsing the string and building the objects by hand. But this morning, I noticed the output of a call to myLocations.ToJson( ). It had the objects the way I expected but there was something else tagging along for the ride:

[
  {"__type":"UrbanLocation:#Trilogy.Gunton.Model",
    "Address":"",
    "Block":"115",
    "Lot":"2",
    "Plan":"2"
  },
  {"__type":"RuralLocation:#Trilogy.Gunton.Model",
    "Lsd":"NW",
    "PrimeMeridian":"1W",
    "Range":"19",
    "Section":"23",
    "Township":"10"
}]

So it seems the JSON serializer *was* including type information, but only when it serialized a list of Location objects, not when it serialized a single RuralLocation or UrbanLocation. So that's easy, once I get the JSON from the server for a location, I can manually add a __type to it in the Javascript and populate it with the typename before I send it back to the server.

I'll admit, I actually did consider such nastiness. But then my well-honed Hack Alert started going off as I hope it did for each of you.

What I really wanted was to have the ToJson method specify the type in the resulting string. And to accomplish that, I modified the ToJson method accordingly (changes in bold):

public static string ToJson( this object obj )
{
    return ToJson( obj, obj.GetType( ) );
}

public static string ToJson( this object obj, Type baseClass )
{
    var serializer = new DataContractJsonSerializer( baseClass );
    var memoryStream = new MemoryStream( );
    serializer.WriteObject( memoryStream, obj );
    string jsonString = Encoding.Default.GetString( memoryStream.ToArray( ) );
    memoryStream.Close( );
    return jsonString;
}

And I modified the final line in GetUrbanLocationAsJson to: Response.Write( location.ToJson( typeof( Location ) ) ).

Now, when I retrieve Location objects as JSON, they have the __type included and I can call myLocations.ToObject<Location[]>( ) freely without having to parse a JSON string manually. Hooray!

Boy, this is so much easier than learning Ruby.

Kyle the Unparsed

Sunday, April 13, 2008

Well here's a fine how-do-ya-do. I'm using the ConventionController from MVCContrib which means I have controls with IDs like dto.JobName and dto.OrderedDate.

Problem is, I can't get at these things by ID in jQuery anymore. "#dto.JobName" in jQuery means (if my memory of CSS serves) select all elements with an ID of dto and a CSS class of JobName. Even if that's wrong, it doesn't matter much. The end result is $( "#dto.JobName" ) returns a useless object.

Current workaround is to select by name. Like so: $( "input[name='dto.JobName']" ) or $( "select[name='dto.JobTypes'] ).

Kyle the Selector

Monday, March 17, 2008

I finally subscribed to Rick Strahl's blog because an inordinate number of my Googling ends up there. It's a little freakish the number of times I've hit his blog and had it solve the exact obscure problem I'm having.

After subscribing and going through some recent posts, I stumbled on his very own Ajax Toolkit. Having had my fill of Ajax libraries of late, I scanned through it and noted it for later reference, paying particular attention to the JSON Serializer, a problem I was trying to tackle at the time. But again, I was kind of averse to frameworks so I moved on.

Fast forward a few hours. I had been fighting with some client-side stuff dealing with a collection of items that I had planned to magically get from the server in JSON form and the time had come to actually implement that. The first attempt was courtesy of Scott Guthrie who outlined how to do it pretty specifically. At the end, he mentions the DataContractJsonSerializer class as a replacement for JavaScriptSerializer and I go about implementing it. Didn't get too far but wouldn't you know it, a Google for implementing DataContractJsonSerializer brings up Rick's blog on the first page and gosh darn if his explanation succeeded where others failed.

But immediately, things start to look funny with the use of DataContractJsonSerializer. All of a sudden I have to start decorating all my domain objects with [DataContract] and [DataMember] attributes. But I started down the path because if I could justify adding attributes for that, it's not so hard to extend the argument to use ActiveRecord which I kind of got excited about because it would make things go that much faster.

So I cut and pasted [DataMember]s until the bovines migrated to the abode and eventually got the sucker writing out a JSON string for my collection as advertised. Then I added an NHibernate mapping to the class...

Until then, I had been playing with everything on the client only and I was dealing with an empty and unpersisted collection of objects. Now it was time to start dealing with persistence so the NHibernate mapping had to be done. It was then that I ran into the problem outlined here. Namely, even when you make the relevant NHibernate types known to the serializer, it still has problems deserializing using DataContractJsonSerializer. And even if it didn't, even someone as loose with attributes as I am has trouble justifying a reference to NHibernate from my domain project strictly so that the sucker can be converted into a string.

At that point, I recalled Rick's West Wind Ajax Toolkit and the JSON Serializer within. And I'm happy to report that it works smashingly. No [DataContract] and [DataMember] attributes. No references to NHibernate from my domain. No workarounds to serialize NHibernate classes. It just plain works. So far at least. Though I'll admit that I had to turn off lazy loading on my object to make it work. A compromise I'm willing to live with for the moment because the collection I'm serializing consists of value objects so there's not much chance of getting too deep into the hierarchy.

And the jury's still out on whether JSON is an easier format to deal with. Yes, it has advantages when dealing with it in client code. But the number of hoops I'm jumping through to get it into that format had better be worth it.

Kyle the Circus Lion

Thursday, March 06, 2008

There's a point to this and a request for suggestions at the end so don't be alarmed by the meandering I'm doing at the beginning.

The Hillbilly is a bit of a black sheep in his family. I have three brothers, all of whom are land surveyors working in the family business in western Manitoba. My mother, a retired nurse, is also on the payroll as the Office Dictator (according to her business card anyway). It's an odd kind of environment out in their world, what I've often called "Deliverance Country". They have theme days like many other companies but you're more apt to hear them celebrate "Potty Mouth Friday", where they swear like sailors all day, rather than "Casual Friday". (We won't go into the details of Racial Slur Wednesday followed by Repentance Thursday.) And their day-to-day activity is that kind of controlled chaos inherent to small businesses that do actual work while the rest of us blither on about whether our corporate portal is using a colour scheme that won't offend the accounting department's hatred of pastel.

They use an application I wrote nigh on eight years ago in classic ASP that makes heavy use of XMLHTTP and DHTML before it had a name that sounded less Klingon when pronounced phonetically. In it, there is a screen that creates a Job object (ok, it doesn't actually use objects because I was young and it was ASP but let's make an ass out of u and me for a minute).

On that same screen, they can attach one or more locations to the Job as well as remove any existing ones. This is done using DHTML to add and remove table rows dynamically to a running list. Behind the scenes, it maintains an XML document containing all the job information, including the list of locations. On form submission, all the form elements are ignored and the XML document is the piece that gets processed.

As I said, this was eight years ago. I'm in the process of updating this same application and my first order of business is to duplicate the functionality of the existing app (which is much more than what I've already described, except for a search feature). And I'm implementing the Edit Job screen and discovering that after eight years, there doesn't seem to be a better way of building this screen.

Yes, there have been advances in scripting languages and techniques. I'm starting to use jQuery which is kilometers/miles faster than using the DOM natively but is not going to win over the hearts of any web developers looking into Javascript for the first time. It's a great framework for those of us familiar with how hard it is to do this stuff without it though.

But I'm talking about the underlying method in which I would build this screen. However cleaned up it may be, there is still direct manipulation of HTML elements. There is still the storage and manipulation of data in the browser. And XML is still a very viable alternative for that storage. I have a feeling JSON might be more suitable but neither option is very palatable.

For example, in C# 1.0, how would you find a particular element in a collection? Loop through the list until you find it. In C# 2.0: probably use the Find method on the list with a delegate. In C# 3.0: lambda expressions maybe.

In Javascript today, as you did eight years ago, you loop through the list. Or you use selectSingleNode on an XML document, just as you did eight years ago.

Now, jQuery does alleviate this quite a bit with some pretty advanced use of selectors. But in the end, you're still searching through an XML document. Or a JSON object which, despite the simpler syntax, still is kind of funky to traverse and add/remove items from.

I'm not sure how my ideal way to build this screen would be exactly. I just have this feeling that, after eight years, it should be easier than it is.

And maybe it is. Which brings me to the real reason for this post. How would *you* build such a screen? Remember, you're adding/removing items to a collection on the page client-side and submitting the data all at once. The items are not selected from a list, they are entered mostly free-form by the user (I'm paraphrasing seriously but don't want to go into the details of the section/township/range syntax). Think of it as creating a shopping list with some extra metadata at the top (e.g. name of the shopper, date the list was made, etc).

Would you do DOM manipulation with jQuery or prototype or whatever? If so, how would you maintain the state of the object in the browser? Or would you have a postback everytime an item was added to the list and maintain it in a state on the server? Or is this something that Script# or something akin was born to deal with? Or...?

I welcome any and all suggestions and would love to post a follow up to summarize them at a later date.

Kyle the Client-Side

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Copyright © 2010 Kyle Baley. All rights reserved.
 
CATEGORIES
.NET General (18) alt.net (4) altnetconf (9) ASP.NET AJAX (40) ASP.NET MVC (29) Bahamas (1) Bahanet (9) BDD (1) Brownfield (18) Career (9) Castle (1) Code coverage (1) Coding Style (6) Communication (1) Community (18) Conscientious Coding (34) Continuous Integration (11) dasBlog (12) Development (16) DevTeach (4) Domain (2) Environment (4) Estimating (1) Featured (14) Flamingo (10) Games (1) Google App Engine (2) GWT (5) Hardware (6) Java (1) Javascript (7) Linq (2) Livelink (6) Lucene.NET (2) MbUnit (1) Metrics (1) Miscellaneous (24) Mocking (4) NAnt (4) NHibernate (12) NInject (1) Office (3) Office Development (6) Open Rasta (1) Patterns (5) Presenting (13) Professional Development (15) Refactoring (10) ReSharper (11) REST (2) S#arp Architecture (5) Security (3) Software (11) Sundry (18) TDD (19) Tools (21) User Interface (5) Utilities (8) Visual Studio (8) VSTO (1) Web development (12) Windows (3) Working Remotely (16) Workplace (3) Writing (4)
 
LATEST POSTS
 
POPULAR POSTS
 
 
ARCHIVE