Extending ASP.NET MVC

It is my pleasure to speak tonight at the SEVDNUG about extending ASP.NET MVC.  This talk grew out of an impromptu talk I gave at Desert Code Camp 2011.2.  The speaker didn't show for a class titled "Real world MVC", so I took it and ran with it.

In this talk we'll look at some common and some less-common extension points for ASP.NET MVC:
  • Routes
  • Route Constraint
  • Html Helper
  • Action Filter
  • Value Provider
  • Action Result
  • Model Metadata Provider
  • Dependency Resolver
The goal is to keep your code DRY (Don't Repeat Yourself), and many of these tools make it much easier to centralize cross-cutting concerns.

Grab the code and slides we'll work with from here.

Desert Code Camp 2011.2

Desert Code Camp is always such a pleasure, and I'm pleased to be able to speak twice this time.  I'm teaching two topics: Backbone and Qunit.

Backbone is an MVC framework for JavaScript.  Much like you wouldn't stick your entire program in a click even handler, why would you stick all your client-side code in a jQuery click event handler?  Backbone gives you the structure to create well architected client-side code.  Backbone is also light enough and modular enough and not opinionated enough to get you quickly to an on-ramp.  Download the slides and sample code we'll play with here.

Qunit is the JavaScript unit test framework used by the jQuery team to test jQuery.  It is a great red/green test harness for doing very elegant testing of client-side business logic.  Download the slides and sample code we'll play with here.

If you enjoyed this talk, leave me a comment.  If you didn't like it, tell me how I can do better.

Rob

Web Forms to Razor

I'm honored to present at SEVDNUG tonight.  Our topic is "Web Forms to Razor".  Our primary focus is getting familiar with the new mechanisms in Razor and MVC, and learning how we can transition a product from one platform to another.

We'll run with the solution here, comparing the Web project (MVC) to the WebForms project.  Both include identical functionality and look & feel.  When we're done, we'll have a good introduction to MVC concepts and in particular Razor concepts -- enough to begin you thinking.  Over the course of the evening, we'll reference Phil Hack's Razor Cheat Sheet found at http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx

Razor and MVC provide a newer, cleaner mechanism for handling web scenarios.  The former paradigm of abstracting HTML and JavaScript away from us has gotten in the way.  MVC gives us a foundation for a clean separation of concerns where it matters, and Razor provides a format for cleanly rendering html.  It's a very elegant stack, and I hope you enjoy this evening's demo.

Rob

Entity Framework Code First

I keep finding myself referring to two links on Entity Framework Code First:
  1. http://www.hanselman.com/blog/PDC10BuildingABlogWithMicrosoftUnnamedPackageOfWebLove.aspx  This is Scott Hanselman's introductory demo to "the unnamed package of love" where he demos EF Code First ("Magic Unicorn"), MvcScaffolding ("HanselScaffold"), Sql Server Compact Edition, and Ninject.  It's one of those videos where I finish feeling like I can take on the world.  It is mega cool.

  2. http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx  This is the Entity Framework team's quick walk-through of EF Code First.  It includes the list of conventions, a quick tutorial on getting going, and nice links to other content.
Those are they.  Now maybe I'll be able to find them easier next time I go looking.  :D

Dependency Injection with Ninject and Mocking with MoQ

Today it's my great pleasure to lead the discussion about Dependency Injection with Ninject and Mocking with MoQ at the SEVDNUG.

Our purpose as software developers is to orchestrate together loosely coupled, well tested components.  Yet far too often, our code turns into a big ball of mud.  These two tools and their supporting techniques can create loosely coupled, eagerly testable code that will make you much more productive.

Our starting place is this, an n-tier app with hard-coded dependencies.  This is very hard to unit test.  I grant there's good separation of concerns here, and that typically that's harder than it looks.  After a brief discussion of the architecture of this app, we'll look for seams in the code -- places where we can insert interfaces and separate the dependencies.  We'll make the adjustments with the help of Resharper, then get Ninject to wire up the dependencies for us.  With dependencies solved, we'll look at unit testing various pieces (time permitting).  We'll instantiate the code under test, and mock the dependencies using MoQ.  Once we're done, we'll end up with something similar to this, an app with loosly bound dependencies, a clean separation of concerns, and good test coverage.  Even more important, we will understand the purpose and benefits of Dependency Injection, and have a firm, practical grasp of how to accomplish it.  We'll also have a firm understanding of mocking, and practical tools at hand to make unit testing easy.

Where can you go from here?  Let's look at unit testing routes, integration testing, continuous integration, etc.  The sky's the limit.

Rob

HtmlHelper for something that isn't the Model in ASP.NET MVC

I'm in the midst of a Razor View, and I want to use things like

@Html.EditorFor(model => model.ProductId)

but the model isn't a Product, it's a composite type for this view that looks like this:

public class SomeViewModel {
    public Product Product { get; set; }
    public List<Irrelevant> IrrelevantList { get; set; }
}

Well, I can say
@Html.EditorFor(model => model.Product.ProductId)
but now the markup on my page says

<input type="irrelevant" id="Product_ProductId" name="Product.ProductId" />

Two problems here:
1. That's ugly.
2. The post ActionMethod takes in a Product, so the model binder doesn't work right.

I really want an HtmlHelper<Product>

So, I gin one up like so:

var ProductHtml = new HtmlHelper<User>( this.ViewContext, new ViewDataContainer2 { ViewData = new ViewDataDictionary<Product>( Model.Product ) } );

and now I can do this:

@ProductHtml.EditorFor(model => model.ProductId)

System.Web.Mvc.Html.TemplateHelpers.ViewDataContainer would be perfect, but it's private, so I cloned it as ViewDataContainer2 like so:

public class ViewDataContainer2 : IViewDataContainer {
    public ViewDataDictionary ViewData { get; set; }
}

Presto, it works.  Both problems are resolved.  Awesome.

Rob

CruiseControl.NET home page link to latest build

I often find that I hit the CruiseControl.NET home page, see red on a build, and specifically want the latest build report. I could click the Project Name link then the latest build link, but that intermediate page isn't buying me much. What I'd really like is the last build time to be a link to this latest build report.

I cracked open the webdashboard folder, and inside the templates directory was the magic sauce. I modified ProjectGrid.vm line 127 from:

    <td>$projectGridRow.LastBuildDate</td>

to

    <td><a href="/server/$projectGridRow.ServerName/project/$projectGridRow.Name/ViewLatestBuildReport.aspx">$projectGridRow.LastBuildDate</a></td>

and I now click on the last build date link and get straight to the last build report. Awesome.

A cool List .Sort() extension method via lambda

Here's an awesome List<T>.Sort() extension method:

    public static List<T> Sort<T,U> ( this List<T> Source, Func<T,U> OrderFunc ) {
return Source.OrderBy( OrderFunc ).ToList();
}

Use it with a lambda like this:

    MyList<SomeClass> mylist = PopulateList();
    mylist = mylist.Sort( i => i.Sequence ); 
ow that's an awesome sort function!

Or like this for non-:

    MyList<int> mylist = PopulateList();
    mylist = mylist.Sort( i => i );

Now that's a cool sort function!

Rob

Google Maps JavaScript API v3 Demo

I was honored to speak at the Google Technology User Group last night.  To combine a love of JavaScript, a very powerful tool, and an audience of enthusiastic fans is an incredible joy.

The topic was Google Maps, and specifically the Google Maps JavaScript API version 3.  v3 simplifies and streamlines the api in some very significant ways over v 2.  Most notably, you no longer need an API key, you only need to include a script tag.  That is awesome!

We started from a wonderfully simple "hello world" map, built up through creating Markers and pop-ups (called InfoWindows), worked through geolocation (address to Lat/Lng) and reverse geolocation (Lat/Lng to address), using the user's location (browser permitting), and handling map events.  The crescendo of our activity was events.html:  When the user clicked the map, we created a marker and sidebar content.  Clicking either the marker or the sidebar content opened the InfoWindow and changed the sidebar's style.  Both the pop-up InfoWindow and the sidebar content included a geolocated address.  Dragging the marker would adjust the address in the pop-up and sidebar.  An [X] button in the sidebar could show and hide the points.  It was truly awesome!  All the code we explored is available here.  There were no slides as everything was a live demo from the code.  The bottom few items on the index page include links to helpful resources, including the official Google Maps Javascript API docs found here.

Rob

Get all Enum values as a List

Often times it's helpful to get a list of all defined values for an enum.  Enum.GetValues( typeof( MyEnumType ) ) returns an Array.  This is less than helpful.  An untyped Array is harder to query against than something much more IQueriable<T>.

So I typically write something like this:

Type t = typeof(MyEnumType);
Array vals = Enum.GetValues( t );
List<MyEnumType> enumvals = new List<MyEnumType>();
foreach ( T val in vals ) {
    enumvals.Add( val );
}

After writing this code a dozen times, it occurred to me that an extension method was in order.  Here's the extension method:

public static List<T> GetListOfEnum<T>() {
    Type t = typeof(T);
    if ( !t.IsEnum ) {
        throw new ArgumentOutOfRangeException( t.FullName + " is not an Enum" );
    }

    Array vals = Enum.GetValues( t );
    List<T> enumvals = new List<T>();
    foreach ( T val in vals ) {
        enumvals.Add( val );
    }

    return enumvals;
}

Call it like this:

List<MyEnum> vals = ExtensionMethodClass.GetListOfEnum<MyEnum>();

(yeah, since I didn't have a this parameter, and didn't really want to create a value to call an extension method, it's really just a static method in some utility class.  That's fine though.)

Ideally I'd like to say where T : Enum (so I'd get a compile error if I passed in a non-Enum T) but where specifically blocks Array, Delegate, Enum, ValueType, and object.  Rats.  Many have argued this should be allowed, but it isn't.  Thus the check / throw at the top.  Some have suggested to use where T : struct or where T : IConvertable first to get 1/2 way there before the run-time check.  In the end, I suppose the answer is always the same: have good unit tests.

The last time I built this (non)extension method, ReSharper asked if it could help.  I said yes, and it turned it into this:

public static List<T> GetListOfEnum<T>() {
    Type t = typeof(T);
    if ( !t.IsEnum ) {
        throw new ArgumentOutOfRangeException( t.FullName + " is not an Enum" );
    }
    return Enum.GetValues( typeof(T) ).Cast<T>().ToList();
}

Now that's pretty compact!  Nice.

Rob