Archive for December, 2009


Here’s an easier way to do dependency injection and build controllers without parameterless constructors in ASP.NET MVC. If you want cleaner code and easier unit tests for your controllers and BLLs, follow the instructions below to use top-down dependency injection using Structure Map.

1. Replace the default System.Web.Mvc.ControllerBuilder with a StructureMap controller factory: First, create a new class called StructureMapControllerFactory in the presentation layer.

using System;
using System.Diagnostics;
using System.Web.Mvc;
using StructureMap;
namespace MyWebApp
{
/// <summary>
/// Used in Global.asax's Application_Start method to replace the default System.Web.Mvc.ControllerBuilder with this StructureMap controller factory.
/// </summary>
public class StructureMapControllerFactory : DefaultControllerFactory
{
/// <summary>
/// Use StructureMap to construct the controller and all its dependencies.
/// </summary>
/// <param name="controllerType">Type of the controller.</param>
/// <returns>A reference to the controller.</returns>
protected override IController GetControllerInstance(Type controllerType)
{
if (controllerType == null)
return null;
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
}

2. Then use the new StructureMapControllerFactory in Global.asax.cs’s Application_Start method. Add this line right below the Bootstrapper.Bootstrap() call:

ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());

3. You don’t need a parameterless constructor for your controllers anymore. Make sure you pass in any dependent blls/etc. in all of your controllers’ constructors (i.e. don’t use ObjectFactory). Like this:

private readonly IMyBLL myBLL;public MyController(IMyBLL myBLL){this.myBLL = myBLL;}

4. Make sure you pass in dependent blls/dals /etc. in all of your BLLs’ constructors (i.e. don’t use ObjectFactory). Like this:

private readonly IMyDAL myDAL;
public MyBLL(IMyDAL myDAL){this.myDAL = myDAL;}

Here’s an easy way to get the MVC root path in JavaScript Js files. Since Js files don’t let you run embedded C# code, and you don’t want to hard code a URL path because the dev and production environments have different root paths, so it’s hard to get properly resolved URLs for JavaScript in MVC. One way to solve this is to create an extension method (JavaScript calls it a prototype) to a global variable in your Site.Master page that automatically converts any reference to “~/” to your MVC root path.
Place this JavaScript block above your links and script references in your Site.Master page (for example, right underneath the head tag).

// THIS MUST BE LEFT AT THE TOP OF THE PAGE...all links and scripts below will need this extension method
// Create an extension method ("resolve") 
that returns the correct server path of the server, whether the server is virtual directory or root
Url = 
function() { }
Url.prototype ={
_relativeRoot: '<%= ResolveUrl("~/") %>',
// create an extension method called "resolve"
resolve: function(relative) {
var resolved = relative;
if (relative.charAt(0) == '~') 
resolved = this._relativeRoot + relative.substring(2);
return resolved;
}
}
$Url = new Url();

Now in any js file in JavaScript that requires an MVC path resolution, just use:

var imageUrl = $Url.resolve("~/mypic.gif");  //’resolve’ is an extension method created in Site.Master

Pros and Cons of NHibernate

I boiled down several lists of pros and cons of using NHibernate into this simplified list. There are only 2 pros, but they’re huge and I showed how all the cons could be easily mitigated. Let me know if you have any questions.

Pros

1) Speeds development.
a. Writing update/insert statements and mapping query result fields to/from object members is slow, tedious, and prone to error. Letting NHibernate do this saves a significant amount of time and lets the developer focus on business logic.
b. The number of unit tests needed to be created and maintained is reduced because all the crud statements go through a common dll.

2) Makes data access more abstract and portable. The ORM implementation classes know how to write vendor-specific SQL, so we don’t have to. This provides a level of abstraction which helps isolate the app from the database. If we need to change our database schema or if we go to another brand of database, we minimize the impact on the code we have to modify in our applications.

Cons

1) NHibernate has a learning curve, but examples are well documented in current 3G projects.
2) NHibernate might be slightly slower because it has to generate sql on the fly, but the performance hit should be insignificant.
3) NHibernate might autogenerate slow sql statements. However, we generate the get statements, so NHibernate isn’t involved with those. Therefore, NHibernate should only be autogenerating update/insert/deletes, which are straightforward. Just to be sure, we can add logging for every sql statement NHibernate generates with verbose logging.
4) Using NHibernate to create a strict separation of tables/classes not good for bulk updates/inserts/deletes (i.e. updating 1,000 objects with new data; moving 1,000 rows from one table to another; etc). Not a problem because we should just execute a raw sql statement for those use cases.
5) Using NHibernate to create a strict separation of tables/classes not good for reporting. Not a problem because we can (and should) create separate business objects for each business use case. A business object does not have to map directly to a table (in fact, with this database design, it probably shouldn’t). For example, a multiple join select statement can be run to generate a collection of reporting objects that can be bound to a report/grid.

Great articles

http://karwin.blogspot.com/2009/01/why-should-you-use-orm.html

Case Studies

NHibernate vs Entity Framework: http://foofish.org/blog/?p=57
NHibernate vs Entity Framework performance test: http://gregdoesit.com/2009/08/nhibernate-vs-entity-framework-a-performance-test/

© 2017 Robert Corvus