Monday, December 01, 2008
Posted on Monday, December 01, 2008 12:02:10 PM (Mountain Standard Time, UTC-07:00)  Comments [9] | 
Categories: GeoWeb | Javascript

Every project is different, so it makes sense to revisit the available tools and select the right one for the job. Here's the landscape as I see it. But first...

Guiding Principal: Keep it simple!

I think this should be everyone's starting position, but it's important to reiterate the importance of keeping things as simple as possible - both for you as a developer and for the end users. Adding in extra "stuff" is not a good idea. Take a read through "Getting Real" by the 37Signals team. They are all about building less, and keeping things simple. This is a major "Web 2.0" idea - keep a tight reign on features - make them prove their worth before letting them into the app.

With that in mind, here's how I look at things...

1) Can I use Google Maps or Virtual Earth?

Since the general public is most familiar with these systems, it makes sense to build on them if you can. Sure there are licensing/advertising issues, but that's to be expected - there is no free lunch when it comes to high-resolution global data sets.

The thing I look at next is data - can the problem be solved with push-pins? If so, we'd write custom data services against a SQL table with Lat/Lon columns. This is blazing fast, and a great solution if it works for your problem.

For non-point data, I'd see if we are talking about lots of features or just a few at a time. If it's just a few at a time, we can send them as geometry (GeoJSON etc) otherwise we'll need a rendering engine to create images, and I'd look at using ArcGIS Server (9.3!) or GeoServer (which incidentally now has support for SQL Server 2008). You can create tile caches, or (with Google) dynamically render a layer. Since the UI and server calls are all under your control, the sky is the limit in terms of what you can do.

2) Can I use OpenLayers?

Even if you are using the ESRI platform, OpenLayers is still a compelling front-end. It can natively consume other WMS/WMS Cache services, GeoRSS, GeoJSON, and a whole host of other things. It has vector editing tools, and support for WFS-T if you have a back-end server that speaks that dialect. It is also open source, has a mountain of unit tests, and is pretty easy to develop with. I'd expect to see someone write extensions for this that can consume layers and features from the ESRI REST API.

3) Can I use the ESRI Javascript API?

If you don't need to pull in non-ESRI external data, then the ESRI Javascript API is pretty compelling. The ArcGIS Online tile caches make for a good starting point, and the map control itself is very nice to work with. To do anything complex, you'll need to get serious with the Dojo Toolkit, but that's worth it regardless of the map canvas you choose. The REST back-end is pretty smooth for simple apps, and when things get more complex, you can always roll your own services (you can read more about that here.)

4) Must I use the WebADF?

Although 9.3 has led to some performance increases, the API is still a huge maze. I think that the breadth of knowledge required to get started with the javascript options often scare off developers. From our experience, while the initial learning curve for the javascript options may seem higher, the effort of developing and debugging even a moderately complex WebADF application vastly exceeds learning  javascript, Dojo/jQuery/ExtJs/YUI, the zen of REST, miscellaneous "HTTP Goodness" and JSON Web Services.

Developing complex sites any any platform is complex, and I'd argue that at least with the javascript options you can "see" everything that's going on (although this has *improved* with 9.3), and have much more control over the UI and service tiers.  Some may disagree with me on that, but that's how I see it. I'm sure you can build a high-performance, user friendly, rock-solid application on the WebADF, but I have not seen such a thing (send Urls if you know of any).

Conclusion...

Keep an open mind, and accept that to build compelling Web 2.0 app, you are going to get some javascript on your shirt. Use some good tooling (Aptana or Visual Studio have reasonable to good javascript support) and it's just not that daunting. Whatever you do, do not pick a technology because it's easier to "get started" with. Look at the longer term, and accept that you'll have to gain some new skills - it's actually pretty fun ;-)

Hey - What about Flash/Flex/Silverlight?

Honestly, I'm just not a Flash/Flex/Silverlight kinda guy - while these technologies can do some compelling things, I'm just not "feeling" it. With the performance increases in Javascript (John Resig compares V8 and TraceMonkey - the "guts" of the newer javascript engines), and the large community of developers working on jQuery, Dojo, YUI, ExtJs and other frameworks, I just don't see a need to graft a client-control into the page. This is not to say you should not do this - if you like it / need it, go for it!

Tuesday, November 25, 2008
Posted on Tuesday, November 25, 2008 11:29:12 AM (Mountain Standard Time, UTC-07:00)  Comments [6] | 
Categories: .NET | Ajax | ASP.NET MVC | Javascript | Unit Testing

We've been having a good time developing applications on the ESRI Javascript API, but we are seeing some limitations to the REST API, and are working around this by creating our own services. Since there are likely others out there who are running into these same issues, I thought I'd share how we are tacking this.

What's Wrong?

Good question, and the answer is nothing. The REST API works quite nicely for a generic API. In the standard scenario, you create an esri.map on the page, setup some tasks (i.e. a QueryTask, FindTask, or IdentifyTask ) and all is well.

out-of-the-box 

Both the map and the tasks are designed to talk to the REST API, and that's pretty good.

But there are some limitations. First, I'd like to do more on the server in a single request. Instead of just locating a parcel by it's PIN, I want to locate the businesses within say 500 yards, and view them on the map and in a results window. Why make multiple requests to the REST API, and write a whole lot of complex javascript, when I can do this in one operation via ArcObjects or <shudder> the WebADF?

Second, given our requirements, I regularly need to access functionality that's not exposed via the REST API - i.e. linear referencing, or 1:M type reporting.

A related issue is that I'd like to be able to write solid unit tests for the code. While it's possible to use something like DOH or jsunit to write unit tests for javascript, it's much easier to write tests in .NET (i.e. TestDriven.netMbUnit & RhinoMocks). So - if I have a choice of making 3 requests to the REST API, and aggregating the results in the browser (in javascript), vs. making a single request to a custom, very testable service, I'll take the second option every time.

Solution: Custom Services

The idea here is pretty simple - instead of using  the out of the box tasks and the REST API, I create my own "tasks" (not real "tasks" in the ESRI parlance - just classes which request and process data) that make calls back to a custom service that does what I want, how I want it.

custom-services

We've done this a number of ways... in all cases we write custom code in one or more "worker classes" that live in a standard class library assembly. Depending on the requirements, these worker classes can be designed to run on a SOC box (i.e. they make direct ArcObjects calls w/o ServerContext.CreateObject), they can run on a web server (i.e. use ServerContext.CreateObject) or if it needs to scale out across a lot of SOC boxes, they can be packaged as Server Object Extensions. Regardless, at the core they are just a set of methods, and so we have another assembly with unit tests that ensures that these methods work as expected.

ASP.NET JSON WebServices (.asmx)

Since all the logic is in the "worker class", the web service is just a thin veneer of serialization / deserialization, most of which is handled automatically by marking up the service as a Script Service.

ASP.NET Handlers (.ashx)

Handlers are very similar to the web service option, but you don't get any json serialization for "free". They are also more difficult to debug and test, so we avoid them. No need to "look for pain" ;-)

ASP.NET MVC Controllers

For a wide variety of reasons, the ASP.NET MVC framework is very attractive - none the least of which is that is was designed to be much more testable than WebForms. We recently did a project that used Controllers as the service tier, and it worked out really really well. As with all things you learn as you go, so I will be doing more active refactoring on the controllers, and taking a more RESTful approach to the URI space in the future.

Summary

I hope this gives you some ideas about how you can "mashup" the ESRI Javascript API with additional back-end services. I have a number of interesting projects that will be doing a lot of this style of interaction, and I'll post more detailed descriptions of them as they go live.

Wednesday, October 22, 2008
Posted on Wednesday, October 22, 2008 1:07:59 PM (Mountain Daylight Time, UTC-06:00)  Comments [3] | 
Categories: Dojo | Javascript | Visual Studio 2008

One big hurdle for developers moving to javascript is the lack of "compile time checking". The only way to see if your code is syntactically correct is to load it into a browser and run it. But, sometimes small syntax errors can cause the javascript parser to fail, and the file will not load. This is a huge pain, and a great way to waste hours trying to find the smallest of syntax errors.

Enter Javascript Validation. There are some on-line tools for validating javascript, and Douglas Crockford's JSLint is likely the most widely known. And while these tools can be handy, copy/pasting code into a text box, validating it, making changes, re-validating etc etc is tiresome.

Luckily for all of us Predrag Tomasevic created a Visual Studio add-in that uses JSLint to validate javascript from within Visual Studio 2005/2008. It's called JSLint.VS, and the code is over at CodeProject. Get it.

The simplest way to use it is to run JSLint on a file from the context menu...

jslint1

But, if you look at the options (Tools --> JSLint.VS options) you can integrate this with your build.

jslint2

You can see the options that I have checked - running with minimal items checked tones things down to just checking for syntax - which end up being the most irritating bugs to catch. For example here is some code that's catching an event, and then propagating that to another method along with some customized event arguments.

onClick: function(evt){
    // stub for event propagation
    console.log("DashboardMenu::onCommandItemClick");
    this.onCommandItemClick({
        action: this._menuConfig.action,
        type: this._menuConfig.type                
    });
},

The customized arguments being passed over to onCommandItemClick are created via object notation - JSON if you will. Since I'm refactoring the code quite frequently, small little things can become problems. For example, I decided I did not need to pass "type" along anymore. Ok, I just went in an deleted that line resulting in this code...

onClick: function(evt){
    // stub for event propagation
    console.log("DashboardMenu::onCommandItemClick");
    this.onCommandItemClick({
        action: this._menuConfig.action,                       
    });
},

And as usual I refreshed FireFox, and followed along in FireBug and all was well and good. An hour or so (and a dozen or more changes) later I tried the page in IE...

ie-msg

Oh sweet. Without getting into dojo.require etc etc, this message is basically saying that IE could not load the class "dts.DashboardController" from the file because of some javascript syntax error. What's not really clear is that the error could exist in that file, or any other class that's dojo.require'd by the specified class. In my case, the code shown above is in dts.DashboardMenu, which is required in dts.DashboardController as shown below...

dojo.provide("dts.DashboardController");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dts.DashboardMenu"); //<-- DashboardMenu is pulled in here

dojo.declare("dts.DashboardController",
    [dijit._Widget, dijit._Templated, dijit._Container],
    { 
        //class definition here...    
    }
);

So - back to the problem - those who work with javascript and JSON every day ,and have sharp eyes might have noticed the error in the second code block - there is an extra comma in the JSON. Firefox accepts this, and works just fine. However, in IE the file fails to parse and we get that error dialog.

Turning on JSLint.VS, I get a notice about the missing comma as soon as I build... with the line number... how easy is that!

jslint3

This will clearly save me a LOT of time over the long-haul - if you are using Visual Studio for your javascript development, this should be a "must-have" addin.