Zen and the Art of ServerObjectExtensions

Posted by Dave Bouwman | Posted in .NET, ASP.NET MVC, ArcGIS Server, ESRI, Visual Studio 2008 | Posted on 14-12-2009

4

I was going to cook up a full SOE example, but that was going to take way more time that I don’t have, so here’s the abridged version – just the major points…

 

Projects in the Solution

SOE’s have a lot of moving parts, so let’s think about all the parts in terms of servers & assemblies.

First – the SOE project. We’ll create the actual SOE’s in here. We can have references to all the ArcObjects / ADF goop we want in here, since this will of course be running on the SOC machine.

In the “client” application (ASP.NET MVC in my case) we’ll use an interface to access the SOE. Since we’ll want the interface definition on both the SOC machine(s) and the “client” machine, we put this in it’s own assembly. Remember that anything that moves between the SOE and the “client” is really doing DCOM under the covers, so all types need to be serializable.

Next up is the Utility assembly. We have a mess of static classes in here that are pure ArcObjects. This assembly will be used on the ArcGIS SOC box, by the SOEs. An upside of keeping this code “pure” ArcObjects (by that I mean there is no ServerObject cruft in here) we can use these same utility classes in ArcEngine or Desktop development.

Finally, we’ll want that “client” application I’ve be talking about. I’m a big fan of ASP.NET MVC, so I’ve been using that to host services. It’s worth noting that you can put standard ASMX SOAP web services into an MVC project. This is nice because you can expose your SOE methods as SOAP or JSON from the same project. Remember, this project will be using the ESRI ADF library to create the connection into the SOC and get access to the SOE, so it will need to run on a box that has these libraries accessible. Note that at 9.4 the ADF components are re-distributable with out incurring additional licensing.

 

Building

The build process can be a little hairy. First off, make sure you have ArcGIS Server on your development box – this way your build/test cycle will be manageable. If you need to copy dll’s to another server as part of your debugging process you will lose your mind.

So – we need to register all the COM assemblies – that would be the SOE, the SOEInterface, and the COMUtility assemblies at minimum. While you *CAN* tell visual studio to register these assemblies for COM interop, DON’T! That will register the assembles in \bin\debug.

A better plan is to copy these dll’s to a separate folder, and install them there. We call ours _install_ComUtilities. We have a post-build event that copies the SOE and it’s dependencies into that folder, and does all the dirty work. Jeff Germain just threw up a good post on a Post-Build Event that does all this, but here’s the basic process:

  1. Stop the ArcGIS SOM Process (SC STOP ArcServerObjectManager)
  2. Un-register the dll’s (regasm /unregister…)
  3. delete the type libraries (*.tlb)
  4. delete the dlls
  5. copy the new dll’s from the build output folder into _install_ComUtilities
  6. run regasm on them to create the type libraries
  7. re-start the ArcGIS SOM process (SC START ArcServerObjectManager)

Now, of course you don’t want to do this every time your solution builds, as it takes ~15 seconds, so use the visual studio configuration manager to not build the SOE project automatically.

Registering the SOE with the Map Service

Get Vish’s SOExplorer app, and use that. You can do this manually or write some code to do it, but just use Vish’s tool. It rocks. Moving on…

Logging

Since you’ll likely have a bug or two in your code, having some logging is really important. We use Log4Net on the client side, but have never gotten this to work smoothly in COM land. Again, Jeff has saved the day with a ComLogger utility that he whipped up for this. I’ve asked him to post about this, but he has not gotten to it yet. If you want this, go to his blog and hassle him.

The upside is that when debugging the app, I’ve got two logs to watch – the log on the client (MVC) and from the SOC (via ComLogger). The ComLogger simply creates a \log folder next to the SOE dll – so you have to watch for permissions on this – make sure that the ArcSOC process has write permission to the folder where you install your dll’s!

Here’s an example of what I get in my SOE Log:

12/14/2009 3:11:37 PM   INFO   LrsSOE::GetRoute   LrsSOE::GetRoute called.
12/14/2009 3:11:37 PM   INFO   LrsSOE::GetRoute   params: routeId: 002B
12/14/2009 3:11:37 PM   INFO   LrsSOE::GetRoute   whereclause: Route = ‘002B’

What shows up in here is up to you, but make sure you stuff all exceptions into the log because that’s where this will save you a ton of time. If you don’t you’ll just get an InteropException on the client side, and that’s completely useless. Also worth mentioning, I use NotePad++ and just keep these two files open in it. When they change, and you change focus to Notepad++, it will ask if you want to refresh the files. Vish is a big fan of BareTail, but from what we’ve see, it’s got wacky behavior on multi-monitor setups. Moving on…

SOAP and JSON in MVC

As noted above I needed to provide services to different clients – one is a Flex app where JSON is convenient, and the other is another MVC app that can speak SOAP fluently. To do this, I just created a standard MVC project, and created a /SOAP folder, inside of which I created a standard asmx web service. By default MVC maps all urls to routes, and so /SOAP would normally route to a class called SOAPController. However, we don’t want that behavior, so we tell MVC to ignore anything under /SOAP (this is in global.asax.cs)

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("SOAP/{*pathInfo}");
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = "" }
            );
        }

For the Json stuff, I setup a JsonController and thus we have routes like http://server/json/getroute?routeId=25b, which of course maps to a the GetRoute method on the JsonController, passing in a routeId of 25b. The logic in the JsonController is pretty simple – we just pass the arguments over to the SOE, and return the response.

Getting the SOE

Getting the SOE itself is a two step process. First you need to get a server context – ideally one that has your SOE registered with it, and then get the SOE from that. We’ve written a lot of these things, so we have lots of handy utilities to handle configuration sections, Identity etc etc. But it boils down to two methods:

public static IServerContext GetServerContext(string arcGISServerName,
                                            string serviceName,
                                            string serviceType,
                                            ESRI.ArcGIS.ADF.Identity identity)
{
    //Connect to ags
    ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsConnection
        = new ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection(arcGISServerName, identity);
    agsConnection.Connect();
    if (!agsConnection.IsConnected)
    {
        agsConnection.Dispose();
        return null;
    }

    //Get the som
    IServerObjectManager som = agsConnection.ServerObjectManager;

    //Get the server context and the mapserver
    IServerContext serverContext = som.CreateServerContext(serviceName, serviceType);

    return serverContext;
}

and…

private ILrsSOEInterface GetSOE(IServerContext serverContext, string soeName)
{
    //Get the server object extension
    IServerObjectExtensionManager serverObjExtMgr = serverContext.ServerObject as IServerObjectExtensionManager;
    if (serverObjExtMgr == null)
    {
        throw new ApplicationException("Failed to get the ServerObjectExtensionManager from the server context.");
    }

    IServerObjectExtension serverObjExt = serverObjExtMgr.FindExtensionByTypeName(soeName);
    if (serverObjExt == null)
    {
        throw new ApplicationException("Failed to get the ServerObjectExtension by extension type name" );
    }

    ILrsSOEInterface lrsSOE = (ILrsSOEInterface)serverObjExt;
    if (lrsSOE == null)
    {
        throw new ApplicationException("Failed to create a reference to the {0} server object extension.", soeName));
    }

    return lrsSOE;
}

Notice that the second method returns the SOE typed as the interface we defined in the interfaces assembly.

Serialization

The last step is to get the results from our SOE back to the client. This is easy for simple types, but as usual Geometry is a pain. The Geometry we get back from our SOE is the SOAP Value type geometry. And as far as we know there is no open API for converting this into a Json geometry. Of course, using Reflector you can *see* that ESRI has all the handy methods you may want to use for this in the REST assembly, but alas they are all internal. What’s a dev to do? I’ve asked ESRI to provide public methods for this, and Morten mentioned being able to do this using the WPF components, but again, the needed methods are internal (and they don’t handle the SOAP value types). If you are working with GeoJSON, the Vish (did I mention Vish rocks?) whipped up GeoJson.NET, which you can get from SVN at Assembla (http://svn2.assembla.com/svn/GeoJSON/) . It cleanly handles the ESRI –> GeoJson formatting. All hail Vish. ;-)

So – that’s a pretty shot-gun style round up of SOE related stuff. If you have questions or ideas, just drop me a line and I’ll see what I can do.

Re-mixing the Flex Sample Viewer

Posted by Dave Bouwman | Posted in ArcGIS Server, ESRI, Flex, Usability | Posted on 18-11-2009

16

The ESRI Flex Sample Viewer is a great starting point for creating map centric RIA’s. The widgetized nature of the starter kit facilitates significant re-use of components, and there are a couple dozen plug-and-play components available from the Flex Code Gallery. Woot!

The downside of this ease of re-use is that we are seeing a new wave of cookie cutter sites out there. It’s great that these sites can the whipped up so quickly, but it’s pretty clear that (for the most part) little or no thought is given to how the user should interact with the site. We see hordes of menus and tons of widgets, all gloriously trying to pseudo replicate ArcMap. Let’s be clear – if your users need ArcMap, give them ArcMap. If they actually know the data model to the point that an ad-hoc query tool will be useful, chances are they will need more functionality than you can build into the Flex app anyhow. Right tools, right place and all that…

Where was I… oh yeah… remixing the sample viewer. When I’m designing an application, I want to build it as focused as possible. Every mouse click and menu drop down I can remove, the better it is for the user. So – here are a few of the things that I wanted from a UI/behavior perspective…

  • I want top level menu items that do something on-click. I don’t want a pull down with a single item on it – I want a print icon that opens the print dialog when it’s clicked.
  • The shortcut menu is a great idea, but I want to have things that “only” appear on the short cut menu. Having something in two places in a UI is counter intuitive in most cases, and wastes UI space.
  • I want to have a limited set of base maps available, and I want them to be displayed as top level icons on the menu. Clicking them will turn on the layer. Active layer should have a “glow” indicating that it’s… well… active.
  • I want widgets that can’t be closed. One thing I’ve seen when letting clients run a Flex app is when they close widgets they are confused about how to re-open it. Thus I want a sub-type of widget that can only be minimized and not closed.
  • I want a full width banner across the top of the page – providing more room for top level items.
  • I want a search box in the top banner so it’s easy to search.
  • I want a zoom to / book mark tool on the top bar so it’s easy to jump to commonly accessed extents

And I want all the same level of flexibility in terms of configuration, and the ability to leverage existing widgets. Now. ;-)

Design Sketches

In coming up with this list of things I wanted, I did some sketches…  (apparently my scanner is crap!)

remix-sketch1

remix-sketch2

In the past I’ve used visio or balsamiq to create wireframes, but more recently I’ve been getting back into sketching simply because it’s so fast. I’ve been using Jason Robb’s wireframe templates as a starting point (article and direct download of pdf).

More Tile Caches…

Since ESRI is changing their caches over to Web Mercator, I wanted to start working with some web mercator tile caches. ESRI has *some* services available now (google search here), but realistically most of these are pretty weak for base maps. So, I created tile layers for OpenStreetMap and CloudMade. Once I finish a few tweaks to these layers (need to display the copyright statements on the map) I’ll release them – likely to the ESRI Code Gallery, but I also want them on a SCM somewhere. Maybe GitHub? Thoughts?

Let’s take a peek…

Things are not fully dialed in yet, and I really need to focus on detailing this out for my client, but this is the generic starting point. I’ll post some live links when my client’s site is ready for beta testing.

remix-mc

This shows the full width banner, the address search, zoom to drop down (needs skinning), an “Always Open” widget, the two base map icons, and the top level print widget. The tiles are from the CloudMade Midnight Commander cache.

remix-2

This one shows the locate dialog that’s opened by running a search from the banner bar. As you can see there are still a few issues with this widget. Since “locate” is not the key focus of the app, this widget can be closed. I’m also going to work on the actual search logic – right now it’s parsing out the address based on commas, and then sending to the ESRI geocoder. I may look at using another service that has more matching logic on the back end so I don’t have to figure out how to de-construct the address.

remix-3

This shows the print widget, accessed by just clicking the printer icon (no drop down required). Oh, and the Open Street map cache in the background.

What’s nice about this is that the user does not need to go digging around in menus to access the functions they need. This template will be used for very focused applications – do one thing, and do it well is the mantra for the project – and so keeping things up front will really help out.

Behind the Scenes

So – the real question is – can we share this? Good question! I’ll be blogging more about how we (big shout out to Jeff Germain who whipped up the “toolbars” stuff) created various aspects of this, and at the very least, you can re-implement most of this stuff pretty quickly. We had to hack at the core of the Sample Viewer (specifically ControllerManager.as) and added a bunch of additional controls for our “toolbars”. At this point things are “working” for the scenarios we need right now, but I suspect we’ll have some refactoring in our future. I’ve got at least 3 apps that will build on this, and by the time all 3 are released, we should have tracked down all the weirdness, and have something that supports all the out-of-the-box Sample Viewer stuff, as well as our extensions. Stay tuned!

Usability for Emergency Response Applications

Posted by Dave Bouwman | Posted in ArcGIS Server, Conferences, Usability | Posted on 17-11-2009

2

I finally got around to loading a video of my talk on Usability in Emergency Response Applications, given at the ESRI South West User Group (SWUG) meeting. In this talk I give a walk-through of an app we built using the ESRI Javascript API, focusing on design aspects that helped streamline the end-user experience. I also discuss the performance impact of token secured services and SSL.

It’s up on Vimeo at http://vimeo.com/7557517 or you can just watch it below…

Usability for Emergency Response Applications from Dave Bouwman on Vimeo.

Using Log4Net in ArcMap COM Extensions/Commands etc

Posted by Dave Bouwman | Posted in .NET, ArcGIS Devt, Utilities | Posted on 15-10-2009

6

I was building an edit task for ArcMap today, and got to a point where I had the geometry operations solid (using Test-Driven-Development for them) but when I got to iterating over sets of real data, I though it would be really handy to use a logger to kick out more detailed debug information. We use log4net in our web applications, so I thought I’d try dropping it in.

Turns out it took all of 5 minutes to get it working, so here’s the how-to (there’s some sample code at the end)

Get log4net

Get log4net from http://logging.apache.org/log4net/download.html – simple.

Add the Reference

Now that you have the log4net zip archive, copy the log4net.dll from the \log4net-1.2.10\bin\net\2.0\release folder in the zip file into your \lib folder. I always have a \lib folder for external assemblies that are used in a project. This is preferable to storing these in a central location because the \lib folder get’s stored in source control along with everything else that your project required. So – if you don’t have a lib folder, make one!

Now that it’s in the create a reference to log4net from your project in Visual Studio.

ref-log-for-net

Configure It

The easiest way to use log4net is with the standard log file appender which just writes to a text file. In order to configure this, we need to edit the ArcMap.exe.config file (located in \ArcGIS\bin). Of course you can store the log in other places (databases etc) – just Google for the details.

By default, this configuration file is almost empty, so you’ll need to add in the configSections as well as the log4net section.

<configSections>
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" 
       requirePermission="false" />
</configSections>

…lower down in the file…

<log4net>
  <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
    <file value=".\\Logs\_log.txt" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%exception" />
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="LogFileAppender" />
  </root>
</log4net>

Now we have to wire log4net into our code. In order to be useful, we’ll want to have access to the “logger” throughout our class, so we’ll make it a private member. Ideally we’d pass in the logger from a dependency injection framework, but we’ll keep things simple for this example (sometimes DI *is* overkill). Thus, we’ll setup the logger in the constructor of our class.

private log4net.ILog _logger;

/// <summary>
///
Constructor.
/// </summary>
publicLRSEditTask()
{
    log4net.Config.XmlConfigurator.Configure();

_logger = log4net.LogManager.GetLogger(typeof(LRSEditTask));           
}

 

Logging

Would not be very much help if I did not show how to actually write to the log! Now that we have _logger, we can just pump data to it. There are a number of levels you use to send out data, depending on the severity. During development, I’ll use the Debug(<info>) method to see what’s going on inside the code, but you’ll also want to use the Warn, Error and Fatal methods when your code experiences errors. Using the different methods allows you to control what’s output to the log file via the configuration section. This way you can leave all that debug stuff in the code, but not have log files piling up on production systems.

In the sample code, I’m just pumping out examples of each type of log.

public void Activate(IEditor Editor, IEditTask oldTask)
{
    _logger.Info("Task Activated.");
}

public void Deactivate()
{
    _logger.Warn("Task Deactivated.");
}

public string Name
{
    get { return "Log4Net Example Task"; }
}

public void OnDeleteSketch()
{
    _logger.Fatal("On Delete Sketch Called");
}

public void OnFinishSketch()
{
    _logger.Error("On Finish Sketch Called");
}

 

In the log file you’ll see something like this…

2009-10-15 15:32:25,631 [1] INFO  Log4NetDemoTask.LogEditTask [(null)] – Task Activated.
2009-10-15 15:32:29,205 [1] ERROR Log4NetDemoTask.LogEditTask [(null)] – On Finish Sketch Called
2009-10-15 15:32:33,003 [1] FATAL Log4NetDemoTask.LogEditTask [(null)] – On Delete Sketch Called
2009-10-15 15:32:38,182 [1] WARN  Log4NetDemoTask.LogEditTask [(null)] – Task Deactivated.

Post Build Tasks

This is a subtle thing, but as far as I can tell, if you want your code to be able to “see” the ArcMap.exe.config file, your dll must reside in the \bin folder right beside ArcMap.exe. This is easily accomplished by adding a post-build event in Visual Studio

copy $(TargetDir)*.* “c:\program files\ArcGIS\bin”

Now, every time you build the project, it will copy your dll and any dependencies (log4net in our case) into the \bin folder.

A final note – when you start using logging, you’ll want to be able to look at the log without re-opening the file all the time. Thanks to Vish I’ve been using BareTail for quite some time now – this app will let you watch the file as lines are added to it.

Here’s a simple sample editing task, along with an ArcMap.exe.config file. Have fun!

Speaking at ESRI SWUG Next Week…

Posted by Dave Bouwman | Posted in Community, Conferences, ESRI, Presentations | Posted on 15-10-2009

3

swuglogo Just a quick note that I’ll be giving two talks next week at the ESRI South West Users Group (#SWUG09) meeting in Pueblo, Colorado. It will be nice to attend another conference that I don’t have to fly to!

I’ll be giving an updated talk on Usability as related to “GeoWeb” applications on Thursday  morning at 10:30am (Room “MR 4/5”). This will draw from some previous usability talks, but without the hard-core developer content, and more focus on the process of arriving at a usable application using ESRI technologies.

On Friday morning at 9:30am (also in room MR 4/5), I’ll be giving a talk for my usual accomplice, Brian Noyle (he got an elk tag, so he’ll be up in the mountains stalking large animals) that will also be about usability, but in the context of an emergency response application we built. I’ll go into the design decisions, the application architecture, and some of the complexities we ran into when building a highly configurable, high-security application that can consume remote map services. If you want to see how far you can push the ESRI Javascrip API, drop by.

Assuming the wireless is stable, we will also be streaming some of the sessions and hope to chat with people on GeoGeek.tv. At the very least, we’ll be recording my talks and hosting them somewhere.

I’ll also be tweeting about the various happenings using #SWUG09 as a hash tag, so you can follow along that way.

Hope to see you there!

GeoGeek.tv: Talkin Flex with Royce Simpson

Posted by Dave Bouwman | Posted in GeoGeekTV, Uncategorized | Posted on 08-10-2009

0

UPDATE: Apparently Royce has been slammed by the flu and will be re-scheduling – we’ll still talk Flex, and other random stuff though

Tomorrow, Oct 9th, we will be chatting with Royce Simpson, the developer who built the award winning City of Greeley “ORIGIN” mapping applications.

image

(Royce is on the right, Brian is on the left, and Jack is givin’ out the hugs)

We’ll talk about his background as a developer, what got him interested in Flex development, we’ll have him take us through the app and discuss various tools and how they were implemented.

Check out the apps, and join the chat to ask questions.

When: Oct 9, 2009 4:00pm MT

Where: http://geogeek.tv/live.aspx 

Follow Royce: @roycesimpson

Rethinking Conferences

Posted by Dave Bouwman | Posted in Community, Conferences | Posted on 06-10-2009

16

Over the last year I’ve been to many geo-conferences, and been privileged enough to speak at most of them. However, I think that there is something amiss in the current conference landscape. To quote Mark Frost in Fortune Magazine…

We’ve all been there: the dull business conference. A half-empty room of half-asleep attendees answer their e-mail on laptops and BlackBerries, while some hapless speaker lumbers through a PowerPoint speech.

How did we get here? I’ve been to somewhere between 50 and 75 geo-conferences over my career, and the dynamic has really changed. It used to be that people we pumped up to attend and were there to contribute and learn. Now it seems that attendees at most main-stream conferences are there to do one of three things:

a) market a product, or

b) present “project work”, or

c) avoid the office.

The rest clearly are not there to contribute, discuss or learn. This becomes blatantly clear when there are no questions at the end of a 90 minute session with 3 speakers. Really? Were you awake? Or maybe everyone is an expert in this niche (if so why is it on the agenda?) Or maybe no one cares about the topic (again, why is it on the agenda?)

That said, some geo-conferences still have a pulse, and I’m thinking of the ESRI Developer Summit and the WhereCamps in particular, but overall, the patient is on life support. What happened?

It’s the Economy Stupid!

While I’m sure that the economy has had a large effect on the overall number of people at any given event, it does not explain the general atmosphere in the sessions. Somehow I doubt the economy been particularly harsh on enthusiastic people. Or maybe organizations are simply sending the “dead wood” out of the office since they are not doing anything anyhow. Regardless, this is something that’s been going on for awhile now, and can’t just be blamed on Wall Street, so lets look at some other possibilities…

Marketing Overload

It seems that an awful lot of sessions are overt or very thinly veiled marketing – typically poorly executed. Some will argue that conferences must support the marketing angle because the sponsors defer a lot of the cost of the event, and thus they need some sort of platform to pitch their wares. However, anyone who’s read Seth Godin’s work knows that the era of “interruption marketing” (follow the link for a video) is on the way out. Pitching your next generation lossless geo-positioned cloud enabled, SOAP serviced, WMS-ified CAD/CAMA integration system to a room of people who don’t know what you are talking about, let alone need one, is a waste of time for all involved. Even if you manage to find the right niche session at the right niche conference, at least make it less “infomercial” and more “how this can help you help others”. Remember – these people did not come to hear a marketing pitch and they are used to Tivo – make them not want to fast-forward you.

If you have to do some marketing at a conference, my advice is simple – give people value: show them how to accomplish something, maybe using your widget/data/process for part of the solution, but offer other options as well. Be authentic. Be open. Be helpful. If you do this, you will connect, and in the end, that’s what you need to make a sale anyhow (unless you’re pitching ShamWow! in which case, stick with the infomercials, and us Tivo owners will never hear you again)

The “Project” Presentation

This should be the meat of most “non-vendor” conferences. We’re here to hear about how our peers are using their skills to make the world a better place. The bizarre thing is that these are usually done like a 3rd grader doing their first “What I did on Summer Vacation” assignment. Reading a bullet list of the ESRI products you used in the production of the city bike lane map is just as boring and useless as it sounds.

Tell us why you did the project and what great things resulted (fewer accidents, better quality of life, lower air pollution). If you did some really awesome stuff integrating systems (and I’m talking about importing an Excel file), tell us both the HOW and the WHY. Context is important. I’ve seen plenty of talks about “boring” topics which were riveting, and many talks on “inspirational” topics killed by someone reading their slideument to a crowd.

Since most people rank public speaking as their #1 fear, here are some useful books – Slide:ology by Nancy Duarte and Presentation Zen by Garr Reynolds. Although commonly cited as resources for good slide design, both books discuss the importance of having a story, the delivery and how to connect with the audience. Anyone presenting at any conference should read these books And if you’re not a natural loud mouth public speaker, they are invaluable. If you need to do a lot of speaking, I’ve heard good things about Toast Masters. And to show you that anyone – even a 5th grader – can give an awesome talk, watch this YouTube video and start re-thinking how you’re going to do things.

Above all – come prepared. I saw one presentation this last year where the speaker ran into the room about a minute before the talk was to start, and clearly had  not even run through her slides before. Sure, expectations are lower than for a TED talk (more on this later), but do us all the respect to bring at least your “B” game, or cancel. Watching someone flounder on stage is horrible (especially if you are not near a door).

Office Avoidance

These are the worst attendees. And what really baffles me is that if you are going to sleep through every session, WHY BOTHER? Just head out to the local attractions, and roll in later in the day for the social events. Having half a room nodding off (partly due to poor presentations) really kills any energy there may have been. So – if you are just avoiding the office, do us all a favor and avoid the sessions as well.

Moving Forward…

I’m not saying I have the definitive answer to the problems outlined above, but here are some ideas. Ideally this will become a conversation and we can set new expectations and chart a new course for our industry. Leave some comments here, or better – write a blog post of your own! Tweet this! Do whatever it takes to get others to think about this because if we all sit back, nothing will change. Let’s be honest – conferences live and die by attendance. Since we can vote with our feet, this is one area where the community has almost absolute power – lets exercise it!

Maybe Less is More?

First, why not scale things back? Who needs 100 conferences each with 10 tracks trying to cover every niche? This makes it more difficult to find great speakers and necessitates huge facilities. What if there were one-half or one-third the number of conferences, and just one or two big rooms at each? And only the most compelling presenters, talking about the most pertinent topics were given a slot on the stage? What if there was more time to actually talk to the speakers or the other people?

Taking a cue from TED

This is the key idea behind the TED Conference. TED started in 1984, and the idea was simple – lets get the best people from the Technology, Entertainment and Design industries together to share ideas. Now, these people are extreme. The cost for the 2010 Long Beach conference is a shocking $6000 a seat (already sold out in case you were wondering). Due to it’s popularity, they are adding a “remote” location called “TEDActive” in Palm Springs, where you can get a seat to watch the streamed coverage for a mere $3750. Not only that, you need to apply to attend – there are essay questions on the registration form (more info here). What’s awesome is that there is ONE conference, with the most kick-ass people across a wide-range of fields attending, and only the most amazing presenters are invited to talk. And even then, they only get between 6 and 15 minutes. Now, you may think that this is just some uber rich event like Davos, but check out these presentations by Hans Rosling, Jill Bolte-Tayor and Josh Silver and get back to me. These are amazing presenters, telling compelling stories about what they are doing, and how they are trying to change the world.

Ok, so TED takes this to an extreme, but right now the geo-conference circuit is so packed with events that we are at the opposite end of the spectrum. There are easily a dozen events a month just in the US. These range from the large events like GEOINT and FOSS4G to smaller events like the Texas GIS Forum or GeoWeb. Every one of these events is vying for and audience and presenters. Maybe cutting things down a little would help a lot? Maybe everyone could bring their “A” game, and we could actually work on solving some real problems? (wasn’t that what got most of us into GIS in the first place??)

It’s about Participation

One way to combat the nodding heads is to keep them involved from planning to the closing. Even at vendor conferences focused on technology transfer (ESRI Dev Summit, Microsoft TechEd & PDC etc.) involving the audience in the planning can have a huge impact. Face it – people are spending a lot of time and money to attend these things, so the more control they have over what they will get out of the event the better.

Conference Planning

The traditional model of peer reviewed conferences, where presenters had to submit a “real” paper, which was then reviewed and published in proceedings is now long gone. Although there are a few “GIS Journals” hanging on, they are a dying breed, and the “abstract” requirement at most conferences is only a formality and a nod to history. The reality is that the “abstract” is really just the elevator pitch. And I commend this – with a bunch of simultaneous sessions, I’m more likely to got to the one with the catchy description simply because the presenter may actually be excited about what they are talking about!

Nonetheless, the abstracts are mostly still selected by a panel, and this has some flaws. The first is transparency -  the people involved in setting up conferences are usually also involved in the industry the conference serves, and thus have some vested interest in particular views. This is not always the case, as evidenced by the GeoWeb conference, which is run by Ron Lake (the father of GML) and Galdos. They had multiple sessions featuring speakers such as Andrew Turner and James Fee who are decidedly not GML apostles.

At the other end of the spectrum here, we have the “un-conference” where sessions are determined on the fly based on who shows up. While this is a really cool model, I suspect (correct me if I’m wrong) there are issues scaling it up and down. There’s likely a critical mass where it works really well, but I can’t see 2000 people coming to a consensus on technical sessions in any rapid manner. And if there are less than 50 participants, finding enough common interests can make things difficult (try being a .NET Developer at a WhereCamp!). In order to convince large numbers of people to spend money and travel, more pre-planned structure is needed. All that said, it looks like this is exactly what the ReadWrite “Real-Time” Web Summit is set to do next week, so maybe we’ll get a sense of how well that works.

Personally, I think something like the SXSW’s “panel picker” can play a huge role. In their system, the audience gets a 30% weighting in the acceptance formula. This sort of a system would help weed out a great many of presentations that people are not interested in, at the same time getting prospective attendees excited about attending.

On-site involvement is also critical. At some conferences, the organizers are now acknowledging the “back channel” by projecting IRC or Twitter streams onto a screen in the room. Since the back channel is going to happen (at any reasonably tech-savvy conference), surfacing it and making it part of the experience is a huge step in audience involvement. Sure, there are risks, like some of the panels at SXSW where the twitter back-channel took on a life of it’s own, but if nothing else it shows that the audience does have an agenda, expectations and since they are already empowered, you may as well work with them instead of against them. I’ll commend ESRI for jumping into the interactive social media pool in a big way following this year’s Dev Summit. Now we just need to get more of the average ESRI Developers/Users on twitter, but that’s a totally different blog post…

External Involvement

Once you accept that the back channel is there, and is public, why not simply stream the sessions? On-site participation will always be a premium because of the face-to-face networking opportunities, but why not chose venues that have solid network infrastructure so that the sessions can be streamed live? This goes back the the idea of smaller facilities – which may actually have better connections! Both WhereCamp5280 and GeoWeb 2009 were at university facilities that had great internet connections. If I can use a $50 webcam and free UStream.TV to broadcast from these events, it’s clear to me that this can be done by any conference. Streaming is not going to cannibalize the on-site audience – those people were not going to come anyhow, but you can enable them to become part of the conversation anyhow. If there is a huge on-line presence for a conference, I would expect that would improve the “brand” of the conference, and I’d bet that it will increase attendees in following years. It also shows that you genuinely care about the community you service. Times are tough, so fewer people can afford to attend, but streaming the sessions enables content to be distributed anyhow. I would hope that large vendor events such at the ESRI conferences would move to this model, but the facilities they host the events at have notoriously poor internet connections. At least they to post the session videos after the fact.

Who’s Leading?

Carsonified hosts a series of events each year – mostly in the UK, but they also have some US dates. While not “geo” specific, these conferences (Future of Web Apps, Future of Web Design, Future of Mobile) are based around the "one big room” model. They get great presenters, stick them in a room with an audience and film everything. You can browse the archives or jump right to a fully caffeinated Andrew Turner talking about “Beyond Google Maps” from 2008. What’s awesome is that the web site that archives the content is a first class citizen in the Carsonified world. There’s the video of the talk, the slides, a highlight reel and sometimes an interview after the talk. Combined with the rich tagging and comment capability, this is an awesome improvement over the current conference web-site model.

However, the <head> conference sounded like a good model for next generation conferences…

<head> is a web conference with all of the traditional elements. We have live speakers, presentations, question and answer sections, and networking opportunities. The twist is that the conference takes place everywhere — all over the world — and at real-world gatherings called local conference hubs.

Live presentations, streamed to local “hubs” all tied in through the internet! Talk about upside for everyone involved – people don’t have to travel long distances, yet the social aspect is still covered by having the local in-person venues! And talk about “Green” – way fewer flights were required, less rental cars and all that hotel laundry!

Who loses in this model? Lets see… those over priced hotels that charge $12.95 per day for unstable wireless, and the airlines. Boohoo.

It does not look like there was a follow up planned for 2009, but I could see this sort of thing changing the game significantly in years to come.

Call to Action!

In this era of cost containment, conference attendees really need to see more value. I’d wager that expenses to send a person to a 4 day conference run between $1000 and $1500. Add in their salary, and the opportunity cost (not having them do the work they are paid for) and you can easily hit $3000 to $5000. Multiply that by 500 or a 1000 attendees and you’re looking at a huge investment pool. The question is: What value are we all getting for that investment?

Right now, the return is pretty poor for most conferences. Between the marketing and the PowerPoint hell, it’s hard to make the case to attend. If they intend to remain part of the landscape, geo-conferences simply have to change. WhereCamps are showing that if the geo-conference community does not get on board, the user community will simply evolve – on it’s own. There are successful models out there, we just need to demand quality and vote with our feet!

Feedback:

I would hope that this post generates discussions around the geo-community, and perhaps some conference organizers might be interested in having a chat. So, if you’ve got some ideas, peeves, or gripes, leave some comments with your thoughts, and I’ll pass them on.

  • What would you change about the last conference you attended?
  • What would you most like to see in future events?
  • Could you attend more conferences if the travel was local (i.e. within 50 miles)?
  • Could you attend more conferences if they had a “real” on-line option (possibly involving some $$)

Creating GeoGeekTV: Domain Model, Controllers and Views

Posted by Dave Bouwman | Posted in ASP.NET MVC, GeoGeekTV, jQuery | Posted on 31-08-2009

2

Now that we have the look and feel stubbed out, it’s time to build out the rest of the site.

Since nearly every page is data driven to some extent, the best place to start is with the domain objects. If we were doing this with Linq to SQL, we’d start by creating the database, and then having that drive our Linq to SQL “domain”, but I’m planning on using this project to get my feet wet with NHibernate, so I’ll just start with the domain.

Since the site is going to be pretty simple, we really don’t have a lot in the domain – really just a ShowModel and a TagModel as shown in the class diagram below.

domain-model

As we can see, these are simple data containers. I had originally thought I’d have a separate “UpComingShowModel”, but it seemed like it would be a pain to copy the info from that model into the “ShowModel”, so I just added an IsPlanned flag. This way I can keep both the upcoming and the completed shows in the same table, side-stepping this entire problem.

Some may ask – why call your domain entities “Models”. Well, that’s a good question. In some other apps I’ve been working on we started off calling the entities Models, and then realized that we needed more than just the entity in the View – so we added a set of “ViewModels” into the mix. This seemed to work pretty well on these other projects, but it does seem a little forced on a project this simple.

Repository

Now that we have the models, we need a way for the Controllers to access them. For that we implement a repository pattern using dependency injection – sounds more complex than it really is.

Essentially we define an interface for a data repository – IShowRepository in this case. This interface represents the contract between the consuming classes (the controllers) and the implementing classes (the data access layer). We then use a dependency injection framework (Castle Windsor via the mvccontrib library) to pass an implementation of the repository into the controller’s constructor. Trust me, this is really easy.

I tend to build these interfaces in an iterative manner – I’ll start with one page of the site, determine what domain objects I need in the controller (and thus the view), then I add methods to the repository interface to get these objects, and then provide the implementation. Here’s the IShowRepository as it currently stands…

repo-interface

After futzing with Visual Studio to show the full signatures (Class Diagram –> Change Member Format –> Display Full Signature), we can see that this is a very simple data contract.

Fakes

Since I want to “prove” the design before getting into actually creating a real data access layer, I start by cooking up a simple fake implementation of the repository. As far as the Controller knows, this is a full blown real-deal repository, but it’s just returning junk. As you can see by hitting the site right now, we are showing lists of shows, but they’re all the same thing – that’s because behind the scenes pretty much everything hits this private method:

private ShowModel CreateFakeShow()
{
    return new ShowModel(){
        Description = @"Dave and Brian talking about recent work,
        building GeoGeekTV.com, Flex, and NBB Hoptober",
        Title = "Friday Streaming from DTSAgile",
        ImageName="123abc.png",
        IsPlanned = false,
        DateLocation= "August 28th, Fort Collins",
        StreamedLive = true,
        ViewCount = 3,
        ShowNumber = 323
        };
}

Dependency Injection

Ok, so we have the interface and a fake implementation, and now we need to get this into the controllers. Since we will be using constructor based injection, the first thing to do is knock in some constructors for our controllers. This is pretty much the pattern for all the controllers.

private IShowRepository _showRepository;
public HomeController(IShowRepository showRepository)
{
    _showRepository = showRepository;
}

Next, we need to register our “fake” with Castle Windsor so it can do the injection. I’ve already setup the basic Castle Windsor infrastructure in Global.asax.cs, so all I need to do is register the fake with the WindsorContainer…

protected virtual void InitializeWindsor()
{
    if (_container == null)
    {
        _container = new WindsorContainer();
        ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
        //add in the components...
        _container.AddComponent<IShowRepository, GeoGeekTV.Fakes.ShowRepository>();
        //Add the controllers...
        _container.RegisterControllers(typeof(LoginController).Assembly);
    }
}

You can get the basic Castle Windsor for MVC setup from looking at either the source code for this project, or from mvccontib’s examples.

That’s about it! With the Windsor container in place, ASP.NET MVC will use it’s factory to create the controller, and along the way all the dependencies get injected. See – I told you it was easy!

Controllers and Views

I’m not going to go the basics of ASP.NET MVC – I’d suggest reading the NerdDinner example from Scott Guthrie, Phil Haak, Scott Hanselman and Rob Conery. I’ll also throw out a pitch for their book, as it is quite good.

In the earlier post I defined the routes, which helped map out the controllers, and the needed methods. Since I’ve built a few sites, and have some handy code lying around, I also inherited my controllers from a BaseController than has some logging capabilities baked in.

basecontroller

Most of the controller methods are very simple – just populate a ViewModel from the repository, and pass that to the view.

This is pretty representative – it’s the Home Controller’s Index method, which is the main page of the site…

public ActionResult Index()
{
    HomeViewModel model = new HomeViewModel();
    model.MostViewedShows = _showRepository.GetMostViewedShows();
    model.RecentShows = _showRepository.GetRecentShows(5);
    return View("index",model);
}

In some projects I’ve had the repository build up the ModelViews, but in this one, it’s easier to have the controller’s handle this, as it results in much less code in the repository.

Summary

So – the project is coming together. Almost all the pages are built out – the Contact page needs serious CSS attention, as well as a back-end implementation. Looking forward, I still have a fair bit of work left to polish everything off. Luckily, I think the enhanced HtmlHelpers in ASP.NET MVC 2.0 will help out. Next up: The Admin Pages

Creating GeoGeekTV.com: Implementing the Design

Posted by Dave Bouwman | Posted in ASP.NET MVC, GeoGeekTV, jQuery | Posted on 28-08-2009

1

Welcome back to my on-going series about the creation of GeoGeekTV.com. With the solution set up, it’s time to setup the master page. For this site I’m using the 960 grid system (960.gs). This is a super easy to use CSS grid layout system. The basic idea is that you start from a 960px wide layout. From there you pick either a 12 or 16 “column” layout for a block of your page (a div), and then drop more divs inside that using classes to specify the width. Sprinkle in some clears, and it all just work. It makes more sense to look at it.

<div class="header">
    <div class="container_12">
        <div class="grid_8">Header Image</div>
        <div class="grid_4">
        <ul id="headerNav">
        </ul>
        </div>
    </div>
    <div class="clear"></div>
</div>

<div class="content">
    <asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
<div class="footer">
    <div class="container_12">
        <div class="grid_5">Recent Show List</div>
        <div class="grid_7">TwitterFeed</div>
        <div class="clear"></div>
        <div class="grid_12">
            <ul id="footerNav">
            </ul>
        </div>
        <div class="clear"></div>
    </div>
</div>

That the stripped down layout for the whole page. We have the three main sections (header, content, footer) which are horizontal color bands in the layout (see the image below). Inside each of them I’ve setup a 12 column container div (<div class="container_12"> ). Inside of that div, I’ve dropped a few div’s with “grid_XX” classes. What’s super cool is that as long as the XX’s in a container add to 12 (or 16 if you’re using the 16 column version) you’re good.

If this does not make sense, take a read at http://960.gs.

From there, I cut graphics out of Illustrator, and implemented a very simple home page.

ggtv-home

You can check out the site as it progresses – I’m now pushing updates to GeoGeekTV.com

Clearly there is work to do on the styling, and I’m going to change up a few graphics, but we’re on our way.

One neat thing I grabbed was some code for putting descriptions over the show screen caps.

ggtv-overlay

As you mouse over the image, the title of the show and the show description slide in. This jQuery goodness is courtesy of Kevin Liew of Queness.com – check out the article for more info. The more I work with it, the more I love jQuery.

That’s it for now. If you want to check out the code, the source is all up at http://subversion.assembla.com/svn/GeoGeekTV

Next up:

Baking the cake with repositories, controllers and fakes! I’ll be creating the domain model, defining the repository interfaces, implementing those interfaces with fakes, and then wiring them into the controllers. Should be fun!

Creating GeoGeekTV.com: Solution Setup

Posted by Dave Bouwman | Posted in ASP.NET MVC, GeoGeekTV, jQuery | Posted on 27-08-2009

5

Welcome back to my on-going series about the creation of GeoGeekTV.com. Now that I’ve got the routes all setup, it’s time to setup the solution.

Typically I break things up into (at least) 4 projects: Site, Domain, Data and Fakes.

ggtv-soln

Depending on what I’m doing I may create 3 more projects that will have unit tests for the previous three (I don’t create tests for the fakes!). Since this site will be pretty simple, I’ll likely skip unit testing for all but the most complex stuff.

So let’s see what’s in these projects

GeoGeekTV.Site

This is the actual ASP.NET MVC project. We’ll have the controllers, and the views in here, as well as some Html Extensions, Action Filters and Services. Since I like to use dependency injection to pass data repositories and other services into my controllers, I setup the mvccontrib WindsorControllerFactory. Since I’m using ASP.NET MVC 2 (Preview 1), I had to grab the /mvc2 branch of the source from github. Everything built smooth as silk, so all I did was grab the dlls and drop them into the /lib folder and make references.

Other items of interest… I’m using a custom authorization filter, which is based on the out-of-the-box Authorization filter that ships with ASP.NET MVC 1.0. Since the source for ASP.NET MVC is available, I could peek at what they did and just change a few things! It’s nice because it ties in with my custom Forms Authentication system, which uses an AccountModel. When a user logs in, their AccountModel is stashed away in session and is used by the Auth Filter to check a user’s roles. This allows us to avoid the Membership provider mess, and just implement things however we want to, all the while hiding the dirty bits behind a nice clean IAccountRepository interface.

GeoGeekTV.Domain

This is where the meat of the project lives – the domain model. In most projects we have the things we need to persist in the database as well as things like SelectLists that are just needed for the presentation in the UI. After trying a number of approaches, I’ve settled on keeping these things separate.  The classes that are persisted to the database are “Models”, and the classes which contain the models as well as the UI extras are “ViewModels”.

This works well because we can create strongly typed views against our ViewModels, which allows us to have all the select-list-drop-down goop and the Model in one handy container, while still keeping them separate behind the scenes. We’ll see how this comes together in a later post.

We also have some utility classes in here, as well as the interface definitions for services and repositories.

 

GeoGeekTV.Data

This is the data access layer, and we’ll have classes in here that will implement the IRepository interfaces. For now there’s nothing in here, but eventually we’ll have our NHibernate stuff in here.

 

GeoGeekTV.Fakes

This is where we fake it till we make it. Basically we implement the interfaces in here, and just return valid, but fake data. This allows me to build out pretty much the entire site without every creating a database. Since it’s just code, any refactoring of the domain or data access interfaces has limited ripple effects. And since we use dependency injection in our controllers, we just change one line of code and the app switches over to the real implementation in the Data project.

Ok, that’s the solution. Next up: Implement the design via a master page.