Thursday, June 12, 2008
Posted on Thursday, June 12, 2008 9:53:19 PM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Dojo | Virtual Earth

We just put up another "demo" site - this time working with Sanborn to provide visualization for their wildfire risk model outputs they have created for the Texas Forest Service. For information on the data, there is contact information on the "About" tab.

txfire

From a technical stand-point, we added a few new features to this viewer...

Dealing with Multiple Tile Layers

The viewer is pulling in multiple tile services, representing multiple layers in a map, as opposed to a single "fused" tile layer. This is the first time I've implemented multiple layers using the ArcGIS Server Tile Cache code, and it turns out it's currently a bit of a pain. For this site, we've got 7 tile layers, and to do that with the current tile server code, I needed to create 7 map services (mxd's), and then configure 7 tile services in the TileServer. Clearly this should be streamlined. For example, the url http://65.101.234.201/tileservice/txfirewfsi/023131001.ashx pulls a specific tile from the txfirewfsi tile service. (shown below)

Tile

However, I'm thinking that it would be nice to be able to add a layer name in the url -'parcels' in this case -   http://65.101.234.201/tileservice/txbasemap/parcels/023133.ashx. This way you could specify the fused tiles, or just a specific layer.

Adjusting Layer Transparency

This was easy, if not obvious. Adding in a Dojo.slider, and hooking up some events was pretty simple. However, it turns out that changing the .Opacity property of a VETileSourceSpecification has no effect after the layer has been added to map. Instead you need to delete the layer and re-add it with the new opacity. Since the browser is caching the tiles, this is actually very fast.

trans

Virtual Earth 3D

This was also the first time I tried throwing things into 3D mode. It took a few quick tweaks in the javascript, and some different CSS for the markers, but for the most part - it "just worked".

tx-3d

There are a few issues with the dojo menus that I'm going to sort out so I'll save the Url for the 3d page until that's dialed.

So, this took about 3 days to pull together -- if you are looking under the covers, the code is VERY "demo" and has some issues - there are a few weird things with the layer list checkboxes and I have not really tested in IE7, and all bets are off with IE6. I'd love to hear thoughts & ideas though.

Wednesday, June 11, 2008
Posted on Wednesday, June 11, 2008 10:47:32 AM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Dojo

Just a quick note that if you've ever run into trouble keeping things positioned correctly in your browser app, take a look at dojo.coords. (ok, the doc is limited, but poke around with FireBug, and it's pretty easy to see what it does)

Basically this allows you to get the top, left, width, height, x and y for any element on your page. I was having issues with my Dojo slider control's positioning when added into the Virtual Earth control via map.AddControl. Basically the control loads just fine initially...

initial-pos

But when the browser window is re-sized, the control remains absolutely positioned on the page, rather than relative to the container (the VE control), as can be seen below.

after-resize

 

Setting the CSS postition:relative, does not work at all, so the solution was to write a little code that would respond to the browser re-size event, and re-position the control. Hooking to the resize event is very easy with dojo.connect... 

dojo.connect(window, 'onresize', positionZoomSlider);

Getting the correct position values in order to calculate the correct position was also easy when using dojo.coords... here's the function that positions my slider.

function positionZoomSlider() {
            //This is needed because the dojo slider seems to always be absolutely positioned.
            //so we attach this to the browser re-size so when things move around, the slider
            //is repositioned correctly.           
            var control = $get('verticalZoomContainer');
            control.style.top =  dojo.coords(dojo.byId('contentContainer')).t + 30 + "px";
            control.style.left = dojo.coords(dojo.byId('contentContainer')).l + 20 + "px";
        }

Monday, June 09, 2008
Posted on Monday, June 09, 2008 9:06:12 PM (Mountain Daylight Time, UTC-06:00)  Comments [3] | 
Categories: ASP.NET | Dojo

So I've been using the Dojo toolkit for a while now, but mainly for the Dijit and DojoX UI components.  For the actual Ajax communication layer,  I've been relying on the Microsoft Ajax framework because of it's seamless integration with the ASP.NET Web Service model. Since I've got the whole mess of Dojo already being loaded into the browser, I figured I should drop the crutches, and work out how to work directly with the Dojo ajax framework.

The one downside of this is that you no longer get the client side proxies for your ASP.NET Web Services. Thus today's article - how to directly access an ASP.NET JSON Web Service using dojo.xhrGet.

Part 1: Create a Web Service

This is pretty simple - just add a web service to your web site. I tend to put the code right in the asmx file, rather than in the code-behind in app_code, but that's just personal preference.

<%@ WebService Language="C#" Class="ASPWebService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class ASPWebService  : System.Web.Services.WebService {

    [WebMethod]
    public string SayHello() {
        return "Hello to Dojo " + DateTime.Now.ToLongDateString();
    }   
}

 

By default your web service will be configured to "speak" SOAP, which is fine if you are consuming it from another application, but for Ajax based browser apps, it's much easier to work with JSON.

Part 2: JSON-ify the Web Service

This is actually really simple - just include System.Web.Script.Services, and the [ScriptService] attribute to the web service as shown below.

<%@ WebService Language="C#" Class="ASPWebService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class ASPWebService  : System.Web.Services.WebService {

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet=true)] 
    public string SayHello() {
        return "Hello to Dojo " + DateTime.Now.ToLongDateString();
    }   
}

We also add a [ScriptMethod] attribute to the WebMethod. We do this for two reasons - first, we want to specify that the response  format should be JSON, and we also want to allow access to this method via http Get's (this is disabled by default).

At this point you can hit the web service in your web browser, and get the standard Web Service browser. But if you also stick /js on the end of the url, you will get the client side Javascript that integrates with the MS Ajax Framework. But we're trying to work with Dojo, so we'll move on...

Part 3: Testing the Service in a Browser

Our simple "SayHello" web method does not take any arguments, so we should be able to just "GET" it via a browser.

The tricky bit that took me some time to sleuth down was that you also need to edit web.config to tell the web service to respond to all Gets and Posts. Add this section (just copy out the parts you are missing - do not paste this whole thing into your web.config or you will get an error!):

 <system.web>
  <webServices>
    <protocols>
      <add name="HttpGet"/>
      <add name="HttpPost"/>
    </protocols>
  </webServices>
</system.web>

Once you do this, you will get the response back. Despite the fact that we have used the [ScriptMethod] attribute to specify that the SayHello web method should return Json, this will only occur if you sent the request content-type to "application/json; charset=utf-8". Without that, you'll still get xml.

Part 4: Create a Simple Page

For this, I created about the simplest page I could - just a button and a div that will be updated. Here's the whole page...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Dojo to ASP.NET WebServices</title>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js" 
        djConfig="parseOnLoad:true, isDebug:true"></script>
    <script type="text/javascript">
    function updateSampleOne(){    
        var contentNode = dojo.byId("sampleone");
        dojo.xhrGet({
            url: "./ASPWebService.asmx/SayHello",
            handleAs: "json",
            contentType: "application/json; charset=utf-8",
            load: function(data,args){contentNode.innerHTML = data.d;},
            error: function(error,args){console.warn("error!",error);}
        });
    }; 
    </script>    
</head>
<body>
<h1>Using Dojo to Consume ASP.NET JSON WebServices</h1>
<input id="btGetString" type="button" value="Update" onclick="updateSampleOne();" />
<div id="sampleone">This will update</div>
</body>
</html>

Breaking down the dojo code...

var contentNode = dojo.byId("sampleone");

This simply get's a the div that we'll be updating.

dojo.xhrGet({
  url: "./ASPWebService.asmx/SayHello",
  handleAs: "json",
  contentType: "application/json; charset=utf-8",
  load: function(data,args){contentNode.innerHTML = data.d;},
  error: function(error,args){console.warn("error!",error);}
});

This is the actual ajax xhr request. Since we are using a GET, we are using dojo.xhrGet.

The Url of our web service is the asmx file followed by the name of the web method. Since it's located in the same folder as this html file, we reference it as ./ASPWebService.asmx/SayHello.

The response will be json, so we set handleAs to json

We set the contentType to "application/json; charset=utf-8" as per the ASP.NET security requirements.

When the response returns, we need to do something with it, this is where load comes in. Dojo uses anonymous functions a lot, and for a simple situation like this, it's pretty easy to follow. The returned JSON is:

{"d":"Hello to Dojo Tuesday, June 03, 2008"}.

So we set the contentNode.innerHTML is set to data.d

Should an error occur, the error function is called.

Summary:

So - while this is a little more convoluted than just using the MS Ajax client library and the Script Manager, it does save us from loading multiple client-side frameworks. Since I'm using Dojo for many other UI components, it seemed a waste to also drag along MS Ajax when this is a viable alternative.

One may ask why use the ASP.NET Web Services model? Well, from the server side it's pretty easy to work with. Once a service is created you can access it via Json or SOAP. They are also easy to unit test.

I'll likely extend this with some more complex examples - like submitting a form, or sending / receiving complex types, but I'll leave it here for now.

Download the sample code

Tuesday, June 03, 2008
Posted on Tuesday, June 03, 2008 10:41:08 AM (Mountain Daylight Time, UTC-06:00)  Comments [5] | 
Categories: Ajax | Dojo

While I've messed with the Dojo Toolkit enough to get the interface elements up and running, I've been delegating a lot of the more detailed "wiring" work to Mike- "soon to be blogging"-Juniper, while I worked on the back end web services and database tiers. When I did wire things up, I tended to use the Microsoft Ajax Client-side Library.

Mike is out at Microsoft TechEd this week, so for my current project, I've got no one to lean on, so I'm digging deeper into the Dojo Framework.

For those not in the ArcGIS Server beta program, it's worth noting that the Javascript API that will be shipping with 9.3 is based on Dojo.

Here are a list of resources that I've been using:

SitePen Dojo Quick Start Guide 

Pretty quick read, but covers the main ideas so well that it has apparently replaced the old "Quick Start" guide that was on DojoToolkit.org

Book of Dojo @ DojoToolkit.org

This is a one-stop shop for what's in Dojo. Quality varies between the sections, but overall, a good starting point for what's in there. Covers Dojo, Dijit and DojoX.

Dojo Feature Explorer @DojoCampus.org

This is another good place to see what the controls can do, and you can see the code as well. Again not 100% complete, but covers much of Dojo, Dijit and DojoX.

Articles @ DojoCampus.org

Be sure to check out the articles on the site. They are pretty focused, but well written.

Have some other great Dojo Framework resources? Drop them in the comments!

Friday, May 30, 2008
Posted on Friday, May 30, 2008 11:26:39 AM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: ASP.NET | DNN | Dojo | Virtual Earth

Starting in February we have been working with the Wildlife Conservation Society to create a map viewer for their Global Avian Influenza site (www.gains.org). This updated viewer launched a few weeks ago, and I thought I'd share a little bit about the project.

About the Project

The project is pretty straightforward, with only a few top level user stories:

- Map the scientific data that has been collected as part of the GAINS program.

- Allow users to filter the displayed this data by :

country,date range,species, and influenza subtype.

Also facilitate this functionality via Url parameters.

- Functionality to be delivered as a DotNetNuke module

- It has to be fast.

Technologies:

We used Virtual Earth for the mapping canvas since WCS needed a high-quality global data set, and this platform is free for non-profits.

For the UI, we dove into the Dojo Toolkit. This ended up working really well, with the exception of the tree view. It was just a huge pain to get the Dojo Tree to work the way we wanted it to, and dropping in the YahooUI TreeView solved these issues in minutes.

On the back end, it's we used ASP.NET. Since this was going to be a heavy Ajax site, we also leveraged the ASP.NET web services which are marked up so that they "speak" json (anyone know if there is a more graceful / concise name for this??? ASP.NET Script Services?). Behind that there is a SQL 2005 tabular database, ArcGIS Server and ArcSDE.

The main UI for the map can be seen below. The data points are clustered, and symbolized based on the match to the filter criteria.

 wme

Data Filtering

The points displayed on the map meet a set of criteria, which can be chosen on this UI. Not that the design is overly beautiful, but it's a mix of Dojo and Microsoft Ajax controls - using the best parts of both. Actually applying this criteria against the database and retrieving the points was non-trivial, so I'm going to write up another post about how we got all that working.

wme-criteria

External Data: Dynamic WMS Tile Caching

The module can be configured to pull in tile services from different WMS servers. This shows my favorite - the global poultry density map. If you are on the site, you can turn these layers on / off this from Map Data --> Manage Atlas Layers. Administrators have a UI to setup the WMS Services. Since mass poultry migrations are rare, most of this data is pretty static. Thus we dynamically cache the tiles on the WCS server so we get improved performance. We do see some offsets in the tiles at the lower zoom levels due to the variations between WGS84 and the Web Mercator projection of VE.

wms-atlas-layers

External Data: GeoJSON Features from ArcGIS Server 9.2

We also have the ArcDeveloper 9.2 REST API for ArcGIS Server 9.2 in the mix, pulling in flyway geometries. For species that have flyways, an extra item shows up in the identify tree. Here's a link to a map showing Calidris alpina, which has flyways. Mouse over a feature, click "View Details" in the pop-up and then expand the tree until you see "Show Flyway". This makes a JSONP call to the REST service running on a different server, grabs the geometries and drops them into the map. Since this species as multiple flyways, multiple polygons are drawn with various colors.

 flyways

It's been a great project to work on, and we are continuing to work with the Wildlife Conservation Society to add additional functionality into this application.

Tuesday, March 18, 2008
Posted on Tuesday, March 18, 2008 8:32:20 AM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: Ajax | ArcGIS Server | Dojo

Based on the Super Tuesday sample site, we got a preview of what ESRI is planning in 9.3.

Map Widgit

Based on Dojox, ESRI has created some wijits (are they dijits if they are based on dojox?) of their own, which we can see in the dojo.require statements...

 dojo.require("esri.map");
 dojo.require("esri.tasks.query");

I'd assume there are more packages lurking around, but this is what I found in a quick look around.

I also noticed something interesting in the constructor for the map - usePlainJson - could this indicate that they have a compressed/encoded Json format? That would be really good, as you can get a lot of bloat when you start shipping around un-compressed JSON geometries. Google uses an encoding scheme, which John O'Brien has written up in an article, and implemented for Virtual Earth so that may also be in the mix.

You can see the javascript for these components here: (it's minified, so it's not exactly readable, but is publicly available) http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1

 

Vectors in the Browser: Dojox.gfx

Dojox is the next generation of Dojo dijits which are pushing the edge of what's possible. The Dojox.gfx package provides an abstraction layer for dealing with vector geometries in the browser - it renders SVG or VML depending on the browser.

I'm glad that we chose to start working with Dojo, as it looks like it will come in handy really soon ;-)

 

In my opinion, the REST services and the Javascript API are "the" 9.3 features, and I'll be focusing most of my attention on this over the next few days.

Friday, March 14, 2008
Posted on Friday, March 14, 2008 5:08:47 PM (Mountain Daylight Time, UTC-06:00)  Comments [2] | 
Categories: Dojo | Virtual Earth

I needed to add a slider type zoom control into Virtual Earth, and since my project is already waist deep in Dojo, it only seemed fitting that I figure out how to use their slider control.

The Dojo framework is an open source client side javascript framework with some pretty nice UI components. You can see the slider here in the Book of Dojo.

Turns out that this is pretty simple to do:

  1. Create the Dojo Slider in markup
  2. After loading Virtual Earth, use map.AddControl, passing in the slider element
  3. Wire up a handler that updates the slider when the map zoom changes
  4. Wire up a handler that updates the map when the slider changes
  5. Sip beer and congratulate your self on a job well done.

Actually the only difficult thing here was divining how to get the slider value - the Book of Dojo is a great general starting point, and the API is too sparse to help out much. There is a Dojo Feature Explorer site that helps though.ve-dojo-slider

You can see a live demo here: http://www.davebouwman.net/examples/vedojoslider.htm

Download the html page

Assuming anyone finds this sort of stuff useful (comment!), I'll post more of these simplified examples using Dojo and YUI with VE.

Friday, February 29, 2008
Posted on Friday, February 29, 2008 4:49:16 PM (Mountain Standard Time, UTC-07:00)  Comments [1] | 
Categories: .NET | Ajax | ArcGIS Server | DNN | Dojo

I've been diggin in deep this week - at 4:30pm on Friday this was my desktop...

desktop

(click to view full res -500k)

I've got the ArcDeveloper REST project up, a testing site where I'm furiously mixing the Dojo Framework with MS Ajax, and a DotNetNuke module where I'm bringing it all together...

wme1

This is just the start, but I've got Virtual Earth in a Dojo Split Container, (there will be a Dojo Tree in the lovely light blue area) with a Dojo Toolbar (icons to be changed). Not shown but also working are some Dojo dialog forms. The orange blob is a feature brought into VE via the ArcDeveloper.net REST service. I still have to wire in some point clustering, and the tree view, but given it's been a productive week.