Visualizing Executive Compensation

Posted by Dave Bouwman | Posted in ASP.NET MVC, ESRI, Flex, IPhone, SQL Server | Posted on 28-02-2010

6

When we heard about the ESRI Mashup Challenge, my team and I knew we were going to enter – the question was just what should we build. About that same time there was another flare up in the righteous indignation about the bonuses paid to AIG executives. We got to talking about how awesome it must be to get a million dollar bonus, and how abstract that really is. Most of us own homes, so we c have some appreciation for numbers in the $250,000 to $500,000 range, but we’re paying those off over 30 years. Making a million dollars in one year, or even better, as a BONUS in one year (regardless of whether or not you drove the global economy off the cliff) is nearly unfathomable. Then it clicked – we’d see if we can find some data that would let us visualize executive compensation packages in a way that we (relatively average folk) can relate to.

Some quick searching took us to a census report stating that the median household income in the US was $50,233 in 2007. So, comparing compensation packages in the 10’s of millions of dollars in a way most people can relate to was going to be a challenge.

The Data

Any compelling mashup needs good data. After some Googling, we found “Pay at the Top” at the New York Times web site. This page listed the 2008 compensation packages for 200 executives at public companies. Now, a web page is not usually that convenient a data source, but this one in particular was built using reasonably clean html. We just grabbed the page source, cut out the section we were interested in, slapped in an XML header, and Jeff Germain went after in using LINQ to Xml, and loaded the data into two tables in SQL Server.

Next up was finding some aggregate income data. Since we wanted to show this on a map, and have the display make sense, we needed to find total income by county. Conveniently the IRS has just such a dataset. Unfortunately the last year they provide data for is 2007. But since we don’t see wild fluctuations in median income levels, this would be close enough (and it was a CSV file, which made loading it painless). Once the data was loaded into SQL Server, we created a spatial view linking these numbers to a county layer in ArcSDE. I prefer using spatial views as opposed to using joins in the map document or actually adding the fields to the feature class because I know I can mess with the data using SQL without any problems.

At this point we could make maps showing all the counties in the country in which the all residents cumulatively made less than any one executive.

Since there are large variations in median income at the county level, we wanted to show, for a given county, how many households does it take to make the same amount as an executive. We were able to pull this data from the aptly name ESRI Median Household Income service on ArcGIS Online.

Flexing the Mashup

We used the Flex API because it’s something we’ve been doing a lot of work with, and the R&D time would pay off on coming projects. The app is a pretty simple flex application, using the ESRI API. We load in a simple shaded relief tile cache as the background, and use a dynamic map service to show the counties.

mashup2

 

Map Services

We are hosting the county income map service (http://204.133.225.169/ArcGIS/rest/services/Mashup/CountyIncome/MapServer), and it’s design is worth noting. We have two layers – one that shows the county outlines, and a second that shades the counties green. Of course we don’t want to show all the counties as green – just the counties where the total income is less than what the executive made. We simply setup the layer in the map with a default definition query of 1=0, which is never true, so no green counties will show up. When we have an executive, we use the Flex API to change the definition query for that layer (on a request by request basis) so that only those counties who’s total adjusted gross income (AGI) is less than the CEO’s compensation. This is a really handy technique which we use a lot.

Web App & Data Services

As usual, we built the back-end of the web app using ASP.NET MVC. The web app has two roles – first, it detects if the request is coming from an iPhone or Android device, and routes the request to a different view that’s optimized for those devices. The second thing the web app does is provide a set of data services to the Flex and Javascript apps (the mobile app is just HTML and jQuery). The data services hit the compensation data stored in SQL Server, and return it to the flex app as JSON.

Mobile View

As I noted the app will present a different view to for iPhone or Android browsers – this is much simpler, but still conveys the same information. The map used is actually OpenLayers, so you can pan & zoom. Mike Juniper and Brian Noyle will be talking more about this technology at their Dev Summit session (1:45pm – 2:15pm Wednesday March 24th)

mashup-iphone

 

The Video

In order to enter the contest, you have to submit a video on YouTube. Here’s ours:

Link: http://www.youtube.com/watch?v=a3dzn9ZxMw8

 

So that’s the app as it stands – I also wanted to give a shout out to Michael Hayden and Bob Binckes who did the bulk of the Flex coding for this – Thanks guys!

There is a lot more that could be done, and there are a few design tweaks I’d like to make, but given the time we had, it came together really well. Check it out and let us know what you think!

http://mashup.dtsagile.com

2010 – A good year for the Dark Arts

Posted by Dave Bouwman | Posted in ASP.NET MVC, Personal, Rails | Posted on 13-01-2010

8

chthulu-railsRuby on Rails may not be on a Lovecraftian list of “Dark Arts”, but for someone who’s been developing on the Microsoft platform for the last 10 years, it’s close enough.

As anyone who’s read this blog in the last 2 years knows, I’m a pretty big fan of Microsoft ASP.NET MVC – it’s simple, gets out of your way, and gives you total control of the output. And it’s 1000% better than the mystery meat known as Web Forms – a nirvana so to speak. So, why would I take up Ruby on Rails?

Why Rails?

First, unless you’ve been under a rock for the last 5 years, you’ve likely heard that Ruby on Rails is *teh awesome*, so that counts for something. Then there is the fact that Andrew Turner (@ajturner for the Twitterati) / GeoCommons crew as well as Paul Bissett / James Fee and the WeoGeo team are all smart as hell, they all love Rails.

And the other reason is that realistically, Apache and Linux have won the web. Yeah there is a large slice of the pie (mainly Government) that runs Windows, but if you are starting a web based business, you’re likely going to run open source because of the costs to start and scale. Sure Microsoft is semi-mitigating this with BizSpark and a few other programs, but regardless, the difference was put in sharp contrast as I tried to negotiate may way around the Microsoft Open Licensing site while at the same time installing RedMine on Ubuntu Linux. For those who have not had the pain pleasure of dealing with the maze of Microsoft Licensing sites, they are among the least usable, obtuse sites anyone could imagine. It’s like they set out to win an award for painful web experiences. Really – I don’t mind paying for software – I love Visual Studio, but why, why, why must it be a living hell to actually login, locate, assign and activate licenses? I’m not joking here – I’m really considering changing from full MSDN subscriptions over to just buying Visual Studio because then we own it outright and don’t have to deal with this crap licensing site every year.

Anyhow… back to my point. On Ubuntu installing software is crazy simple – “sudo apt-get install <software of choice>”. Yes, the command line syntax is slightly more complex than a “Ok-Next-Next-Next” windows installer, but it’s also free, immediate and you’re always getting the latest and greatest.

When the main reason we use MSDN over just Visual Studio is for the SQL Server and OS licenses, it makes me question things – I can install MySQL in about 5 minutes, it’s 100% free and I don’t have to fight with the Microsoft sites? The OS is free, and Aptana RadRails (free) covers the IDE side of things? Why is it that I’m shelling out $15,000 a year in licensing, only to have the entire Microsoft interaction be painful? Ok this is degrading into a rant, but what the heck, I don’t rant very often, and it’s my blog anyhow… moving on ;-)

Ruby on Rails. Yeah. So, it seemed that expanding my horizons a little may be interesting, and worth some evening time. I started with “Rails for .NET Developers” from Pragmatic Press. This is a perfect read if you’re a WebForms developer, and pretty good if you’ve elevated your game to MVC. From there I moved onto “Agile Web Development with Rails” and this is a great follow up. If you like Pragmatic Press books, these are perfect.

Patterns nom nom nom…

Since Rails is  based on the MVC pattern, and a major influence behind ASP.NET MVC, it’s not surprising that the carry over from ASP.NET MVC is huge. The View syntax is very very similar, the the extent that many of the HTML helpers are very similar. This is great because I was immediately comfortable with the general structure of things. However there are some differences… namely data access (aka ActiveRecord)

Because this post is rife with asides, let’s have another… It’s interesting that Rob Conery, of Hawaii and various levels of internet fame (creator of SubSonic, an ex-Microsoftie and now TekPub.com dude) seems to have been going through a similar thought process / experience as I have, although he seems to be a few weeks ahead of me. You see, while I really like ASP.NET MVC, there is still WAY too much time spent thinking about data access. In the last year, we’ve used the Repository pattern, with a mix of SubSonic, NHibernate and plain ADO.NET. On every project there is much hand wringing and thought about how the data access tier should work – how “POCO” should the POCO’s be, what handles the transition from the data tier to the models etc etc etc. In this post about Entity Framework and NHibernate Rob makes the point that we should be waaaaay past thinking about the data tier. It should be “done” – the fact that there are still flame wars about data persistence options is sad. Isn’t a framework supposed to *help* you with the mundane stuff?

I can haz Data Nao?

I my mind, time spent futzing with the data tier is time wasted. Yes, there are projects where you don’t control the database, and some DBA’s do some really wack stuff (if we meet, ask me about this, have I got stories!), but in an ideal world you turn down those projects. Any database that makes it a royal pain to get to the data the users need, is poorly designed in my opinion. The app is about users, and it succeeds or fails based on them, not based on some idealized 4th normal form, so let the app dictate the data model!

What rocks about Rails is that data access is “just done”. No thinking, it’s just done. And it works. Let me say that again – the data access is “just done”. You can go from zero to editing data in your database in about 30 seconds. Sure the styling of the scaffold sucks, and it’s not the best workflow, but the key feature – create / edit / update / delete data in your database is DONE. All that time you would have spend thinking about NHibernate caching or optimization can be spend working out a better workflow or UI styling. Under the covers, I’m sure there are more elegant solutions, and there are likely some performance issues, but realistically 99.99% of web apps are not FaceBook or Twitter, so the performance / scalability arguments are moot – we’ve got trivial numbers of users and heinously powerful servers. Let’s NOT sweat performance mmmkay?

The other thing about Rails that’s great is that it’s opinonated. And not just mildly, it’s got some really strong opinions, but if you can work with them, and not against them things flow so smoothly. I know, I know, I heard this same speil for a few years, but I have to say it’s true. If you can live in the 80% case, Rails makes things so smooth it puts a grin on my face.

What Now Brown Cow?

So, am I forsaking all that Redmond hath wrought? Not quite – this is good kool aid, but I’m not about to throw out ASP.NET MVC just yet (we did just shell out for another year of MSDN after all!) but Rails provides an exciting alternative that’s close enough to the tooling and workflow of my day job that it’s providing inspiration and ideas about how to be a better ASP.NET MVC developer. It’s a great developer exercise to learn a new language or framework, and I heartily recommend checking out Ruby and Rails.

Anyhow, to close out this rant of a post, I’ll be throwing more Ruby into the mix here and on GeoGeek.tv. At this point I’m certainly still very NOOB in terms of Rails, but what I’ve done, I’ve liked. Alot. And as far as “on my own time” projects, I’m sensing a definite shift to the dark side. Welcome to 2010!

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.

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.

Creating GeoGeekTV: Setting up Routes

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

4

Welcome back to my on-going series about the creation of GeoGeekTV.com. Having solidified the design, we can move on to the implementation.

Since ASP.NET MVC abstracts the requested URL from actual files on disk (as in /foo/bar.htm does not actually load a the bar.htm file in the foo folder), we have a lot more control of the Urls. Thus, it’s worth taking a little time at the beginning of a project to decide how we want the Urls to work

For GeoGeekTV, we have a few main areas: Home Page, the Live Stream, Upcoming Shows, the Archive, a Contact page, Backstage and Admin.

Since most of these are pretty simple pages, we can use the default routing for the most part.

The default route  uses the /{controller}/{action}/{id} pattern to make an incoming request to a controller and action (aka a method).

When we setup routes, we assign defaults to the components of the route. So for our site, we users to land at the home page, so we setup the default for the route to be “home”. As for a default action, we usually use “index”. Since an id does not have much context on some controllers, we default that to an empty string.

This is what the route looks like in the Global.asax.cs file:

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

I like to map out the urls for an application in a table. This helps get an idea of how the routes should be setup, and it also provides a development road map for the controllers and actions we’ll need.

Url Controller Action Description
/Home Home Index The home page
/Live Live Index The live streaming page. If we are not live, show a list of recent shows
/Archive or

/Archive/List
Archive List Paged list of Archive shows
/Archive/View/{name} Archive View View a show from the archive
/Archive/tag/{tag} Archive tag View list of shows that have a particular tag
/Contact Contact Index The Contact form
/Backstage Backstage Index The backstage page
/Upcoming Upcoming List List of upcoming shows
/Upcoming/Edit/{id} Upcoming Edit Edit an upcoming show
/Upcoming/Create Upcoming Create Create an upcoming show entry
/Archive/Create Archive Create Create an entry in the archive
/Archive/Edit/{id} Archive Edit Edit an entry in the archive
/Login Login Index Login screen
/Admin Admin Index Main Admin Screen

Conveniently, for GeoGeekTV.com we can pretty much live with this default route, with one exception.  We are going to support a simple tagging system on the shows, and it would be handy to have a url that would list all the shows related to a tag. Now, if we wanted to use the ID of the Tag in the url (i.e. the “Unit Testing” tag has an ID of 27, so the url would be /Archive/Tag/27) our default route would still work. But I think it would be more useful to have human readable tags, so we’ll use the actual tag in the url.

So I’ll create an additional route.

routes.MapRoute(
    "Archive",                                                // Route name
    "Archive/Tag/{tag}",                                      // URL with parameters
    new { controller = "Archive", action = "Tag", tag = "" }  // Parameter defaults
);

This new route is very specific – it only applies to the /Archive/Tag url, and will now pass in a parameter named “tag” to the controller method.

 

Testing the Routes

We can write unit tests to ensure that the routing is working as designed. Since this is just testing the routing, we don’t actually need to create any controllers or views – we are just testing the routes in Global.asax.cs

[Test]
public void archive_tag_tag_route()
{
    MvcApplication.RegisterRoutes(RouteTable.Routes);
    var httpContext = MockRepository.GenerateStub<HttpContextBase>();

    httpContext.Stub(x => x.Request).Return(MockRepository.GenerateStub<HttpRequestBase>());
    httpContext.Request.Stub(x => x.PathInfo).Return("");
    httpContext.Request.Stub(x => x.AppRelativeCurrentExecutionFilePath).Return("~/Archive/Tag/foo");

    var routeData = RouteTable.Routes.GetRouteData(httpContext);
    Assert.AreEqual(routeData.Values["controller"], ("Archive"));
    Assert.AreEqual(routeData.Values["action"], ("Tag"));
    Assert.AreEqual(routeData.Values["tag"], ("foo"));
}

Although this is somewhat long-winded, and there are other more elegant options, I just keep this snipped of code lying around and drop it in as needed.

Although pretty simple at this point, I’ve pushed this into the repository over on assembla.com if you want to check out the code.

Up Next:

We’ve already created a simple out of the box ASP.NET MVC 2 web application. Next time we’ll layout the other projects in the solution, clear out the un-needed cruft from the MVC project and setup our dependency injection. From there we’ll actually start writing some code!

Creating GeoGeekTV: Design

Posted by Dave Bouwman | Posted in ASP.NET MVC, Design | Posted on 20-08-2009

4

Over the last few days I managed to find a little time to work on the design of the site.

The first thing I did was mess around with some fonts and color schemes for the main header of the site. I really like DaFont.com because you can view samples of the fonts using a custom string – GeoGeekTV in my case.

dafont-example

In the end, I stuck with the “sketch” style font I had used in an earlier mock up. With that decision out of the way, I started playing with colors, and whipped up some combinations in Illustrator.

ggtv-header-comps 

Once I picked the color scheme I liked, I moved on and cooked up this layout of the main page.

GeoGeekTV Layout

(click image to view larger)

I’m pretty happy with the design at this point (I’m certainly open to feedback too!). I’m sure it will evolve as I build out the site, but it’s a good place to start.

Up next – designing the routing and setting up the ASP.NET MVC project structure.

Behind the Scenes: Creating GeoGeekTV.com

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

2

For a while now I’ve been wanting to do a “behind the scenes” series of posts where we showing how we work, but most of our projects are either sensitive in nature, or just too large to do without making it a 200 part series. I was also following along last week as the team at Carsonified.com whipped up a simple ASP.NET MVC app. I thought this was particularly interesting to follow since these guys are usually a Ruby shop.

Anyhow, since I’m just starting to build GeoGeekTV.com, I thought this was as good an opportunity as any.

The Goal

As nice as UStream.tv is, I’d rather like to have better “experience” for GeoGeekTV.com. I still want to keep is really simple, but just make it a little smoother to locate archive shows, and to see what we have upcoming. We also want to have a consistent location to watch the “live” stream.

Wireframes

To start off, I fired up Basalmiq (full disclosure – they hooked me up with a license if I blogged about it – I’ll do a specific post in it’s pros and cons another time). In the past I’ve used Visio for developing wireframes, but the tendency there is to get too involved in making it look “real”. For me at least, wireframes are more about figuring out the basic interaction model – how is the information organized, and how does a user navigate it. I’m not worrying so much about colors and fonts. Baslsamiq helps with this because it looks hand-drawn. This seems to help people focus on the flow instead of the looks.

Here’s the initial cut at the UI

GGTV-home-sm

Ok, so I did play with photoshop today and throw in a quickie site header, but you get the idea.

Keepin it “Agile”

In the past I’ve talked a lot about agile practices, so in keeping with that I’ll be keeping track of user stories and tasks at Scrumy.com. You can see the project by heading to http://www.scrumy.com/geogeektv but the screen cap below pretty much sums it up.

scrumy

Basically this is just a digital version of sticky notes. Since this is the free version, I think anyone can change or move things around, but please don’t ;-) Also – since this is a side project, I’m not really working in “sprints” per-se – I’m just doing tasks as I have time – I *hope* to have this all up and running for the next conference we attend (GIS in the Rockies).

Moving Forward

I’ll be working on furthering the design and graphics over the next week, and then I’ll start on the coding. I’m going to be using ASP.NET MVC v2 (beta) because I want to play with the nifty new bits, and I may use this as an opportunity to mix a little Fluent NHibernate into my bag o tricks as well. I’m going to throw the code up on Assembla, so anyone will be able to peek inside.

ASP.NET MVC Custom Authorization ActionFilter

Posted by Dave Bouwman | Posted in ASP.NET MVC, Security | Posted on 22-07-2009

3

The out-of-the-box ASP.NET MVC Authorization filter works nicely if you are using the out-of-the-box ASP.NET Membership and Authorization (roles) capabilities. However, we never seem to be able to utilize them directly because our clients have existing user databases, or we need a richer “user” schema.

Of course we could implement custom providers to plug a different database into this framework, as detailed at MSDN, but this rubs me the wrong way. If my application is going to use a repository pattern for data access, and I’m going to have specific controllers and views for creating/editing users, why should membership and authorization be routed through this other framework?

So, we’ve been “rolling out own” so to speak. We still use System.Web.Security.FormsAuthentication to set cookies, but other than that, we’re on our own. One side-effect of this is that we need to create our own Authorization ActionFilter which will allow us to decorate our controller methods to restrict access based on roles (we dropped the option to restrict by user name). For those not working with ActionFilters yet, this is what it looks like in code.

[Auth(Roles = "Role1, Role3")]
public ActionResult Index()
{
    //do things...
}

By decorating this controller method with [Auth(Roles = "Role1, Role3")]  we automatically restrict access to users who are in “Role1″ or “Role3″.

If someone in Role2 tries to call this method (i.e. they have typed in the url, or were sent a link which they try to visit after logging into the system) we want that logged, and we want the user notified that they have reached an invalid page. We don’t want to just bounce them to the login screen which is confusing.

Since we do use session in the application, we want this filter to also check to make sure the session is valid, and if it is not, redirect the user to the login page, with a message that their session has timed out.

Since this is pretty divergent from the System.Web.Mvc.AuthorizeAttribute  behavior, I thought it best to re-implement instead of inherit and override. So – I just popped over to CodePlex, and grabbed the source for AuthorizeAttribute, dropped it into my class, and started changing things.

As I mentioned, we use session state, and one thing we store is the user’s “Account”. This is held in an ApplicationState object in the session. So the first thing we need to do is get the session…

/// <summary>
/// Gets the session if it exists.
/// </summary>
/// <returns></returns>
private ApplicationState GetSession(HttpContextBase httpContext)
{
    var sessionObject = httpContext.Session[DRCOGApp.SessionIdentifier];
    if (sessionObject != null)
        return sessionObject as ApplicationState;
    else
    {
        return null;
    }
}

 

If get a null back from this call, we redirect to the login…

//See if the session is active
ApplicationState appState = this.GetSession(filterContext.HttpContext);
if (appState == null)
{
    //redirect to login w/ message
    filterContext.Result = new RedirectToRouteResult(
      new RouteValueDictionary {
      { "message", "Session Timed Out" },
      { "controller", "Login" },
      { "action", "index" },
      { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
    });
}

Assuming we get past that, we check for roles, if they were specified. If roles are specified, then the rolesSplit array will be populated. To make this a little cleaner we added an IsInRole method to our Account class, which allowed cleaner syntax in the if clause.

//Get the user
Account user = appState.CurrentUser;

if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
{
    UnauthorizedModel model = new UnauthorizedModel();
    model.CurrentUser = user;
    model.Message = "The resource you attempted to access is restricted. This access attempt has been logged.";
    ViewDataDictionary viewData = new ViewDataDictionary(model);
    filterContext.Result = new ViewResult { ViewName = "~/Views/Error/Unauthorized.aspx", ViewData = viewData };
    //If the controller is not null, use it's logger!
    if (filterContext.Controller != null )
    {
        MyApp.Web.Controllers.ControllerBase ctl = filterContext.Controller as MyApp.Web.Controllers.ControllerBase;
        ctl.Logger.Log.Warn("Unauthorized attempt to access " + filterContext.HttpContext.Request.RawUrl + " by " + user.Login);
    }
}

The real fun happens in this block. If they are not in the role, we want to return a page which notes that they do not have access to the specified resource, and we want to log that.

Setting the filterContext.Result to the correct ViewResult was pretty straight forward, but it took a little longer to sort out the logging.

Basically, all our controllers inherit from a custom ControllerBase, which requires an instance of ILogService on it’s constructor. The injection is handled by Castle Windsor, via mvccontrib so it’s completely unobtrusive. It just took a while to realize that we could access the controller from the filterContext (a instance of AuthorizationContext). Once we had the controller, we use the logger, and we’re done.

Overall, this seems to be working pretty well. Once we’re really sure it’s bomber, and I’ve found time to decouple some aspects of it from this particular project, I’ll post the source code – in the meantime, grab the source from CodePlex and have fun rolling your own AuthorizationFilters!