Compact CSS And Javascript With MVC And SquishIt

SquishIt

SquishIt is a library for ASP .Net implemented by Justin Etheredge of CodeThinked that will take several separate javascript or CSS files and produce a single compacted file as ouput which is then returned to the client, rather than the several individual source files.

This is great as it saves bandwidth by both reducing the number of requests that need to be made, as well as compacting the files by removing excess white space and comments.

Less

One of the additional benefits of using SquishIt is built in support for dotLess. dotLess is a .Net port of the CSS extension Less, which was originally implemented for Ruby. This adds a number of neat features such as variables and mixins, which makes it easier to create well structured and maintainable CSS.

@brand_color: #4D926F;

#header {
h2 {
color: @brand_color;
}
}

Compacted

To make use of Squishit, all we need to do is change how we reference our CSS and javascript files. Instead of including tags in our <head> element, we make a call to Bundle.Css() or Bundle.Javascript() instead:

@MvcHtmlString.Create(Bundle.Css()
.Add("~/Content/style.less")
.Add("~/Content/jq.datatable.css")
.Add("~/Content/jquery-ui-1.8.14.custom.css")
.Add("~/Content/colorbox.css")
.Render("~/Content/Site.min.css"))

@MvcHtmlString.Create(Bundle.JavaScript()
.Add("~/scripts/jquery-1.6.2.min.js")
.Add("~/scripts/jquery.dataTables.min.js")
.Add("~/scripts/jquery-ui-1.8.14.custom.min.js")
.Add("~/scripts/jquery.colorbox-min.js")
.Render("~/Content/Site.min.js"))

In release mode this will combine the separate files into a single file with the specified name, as well as performing minification.

When running with debug on in your web.config (<compilation debug="true">), the files are not combined by default. You can alter this behaviour by chaining a call to ForceRelease() before the call to Render(). Likewise, a call to ForceDebug() can be made to keep everything seperate when doing a release build with debug off.

Using Multiple Layouts

It's not uncommon to have multiple layouts when developing a production web site with MVC3. There is a consideration to be made here, as if you wish to include different CSS / Javascript depending on the current layout, if you use the same output filenames for each layout, it could cause SquishIt to re-minify the files if going from a layout that uses one set of files, to one that uses a different set.

There are two ways round this:
1) Include all CSS and all Javascript for the entire site when bundling. You could extract this to a partial view that is included by each layout so that it only needs updating in one place.
2) Change the name of the output files depending on the view. This will ensure that re-minification only occurs when there are actual changes to the source files.

Permissions

One thing to note is that when using a release build, SquishIt may require write access to the directory containing the target files, which in our case is ~/Content. This is because should any of the source files be updated, SquishIt will want to output a new 'squished' version.

Summary

SquishIt takes all of your javascript, all or your CSS and squishes them into the smallest size it can. This is great in a world of heavily interactive web sites where the weight of scripts and CSS can add significant time to the loading of a page.

Razor And HtmlHelper Extensions

HTML helpers can be fantastically useful when working on an ASP .Net MVC project, and they're dead simple. They boil down to methods which are used to encapsulate functionality to help reduce the amount of logic we end up with in a view.

For example there are helpers available to create labels and form fields, taking a property as input, and generating the relevant HTML for it.

Writing your own HTML helpers is easy and achieved by writing an extension method for the HtmlHelper class. I often hit a stumbling block when writing an extension which manifests itself in the following way:

Compiler Error Message: CS1061: 'System.Web.Mvc.HtmlHelper' does not contain a definition for 'TestMethod' and no extension method 'TestMethod' accepting a first argument of type 'String' could be found (are you missing a using directive or an assembly reference?)

An Example Extension Method

To demonstrate how to fix this, we need a quick example of an HTML helper extension method:
namespace MVC3Test.Helpers
{
public static class HtmlExtensions
{
public static MvcHtmlString TestMethod(this HtmlHelper htmlHelper, string input)
{
return MvcHtmlString.Create(input.Trim());
}
}
}

Make it work

The problem is caused by the fact that we don't have a reference to the namespace where the extension method lives. We have two options for fixing this:

Add a using directive to the view

The first thing we could do is just add a @using directive to the top of the view specifying our helper namespace:
@using MVC3Test.Helpers

Update View Folder Web.config

Adding using directives to each view that uses our helpers will quickly become tiresome. An easier way to apply this throughout the project is to update the web.config to reference the namespace.

This can happen at either the view folder level, or application folder. Either way, you need to update the web.config to add a new namespace entry, which should look something like this:


...

...

Summary

Html Helpers are a great way to reduce the complexity of your views and reuse code that is often repeated.

Just remember that when writing your own, it must be referenced from either the view, or web.config!

Ninject, MVC3 And Web Requests

Continuing to play with Ninject and MVC3, I wanted to explore further how Ninject can help manage objects over the life of a web request. One of the great things about Ninject is that it allows you to easily change the scope in which objects live through use of Activation Behaviours.

Behave Yourself!

Using Ninject, you can control when new instances of objects are created with Activation Behaviours (although this documentation appears to be out of date at the time of writing).

To set the activation behaviour of a binding, you append a call like so:
Bind().To().InTransientScope();

Ninject has the following scopes built in:

  • TransientScope: A new instance is created for each request.
  • SingletonScope: Only a single instance of an object is created, and the same instance is returned every time.
  • ThreadScope: A new instance is created for each thread.
  • RequestScope: A new instance is created for each web request.

RequestScope and MVC

What I was interested in was whether the RequestScope would create a new instance of something at the start of a web request, and then immediately clean said object up at the end of the request, so that objects wouldn't be kept around longer than they were needed.

A simple test ensued:
public class MvcApplication : NinjectHttpApplication
{
private static ILog logger = log4net.LogManager.GetLogger("default");

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

}

protected override Ninject.IKernel CreateKernel()
{
return new StandardKernel(new MyModule());
}

protected override void OnApplicationStarted()
{
base.OnApplicationStarted();

AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}

public class MyModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind().To().InRequestScope();
}
}

public interface ITestInterface { }

public class TestClass : ITestInterface, IDisposable
{
public void Dispose()
{
System.Console.WriteLine("Disposing");
}
}

public class HomeController : Controller
{
ITestInterface test;
public HomeController(ITestInterface test)
{
this.test = test;
}

public ActionResult Index()
{
return View();
}
}

All I did here was setup a controller that would take an instance of a disposable test class. We know it gets created and passed to the controller, so all I wanted to see was that it was disposed at the end of the request. I did this by setting a breakpoint in the dispose method of the class and debugging through Visual Studio.

If you run up the project, you'll see that the breakpoint gets hit after the request has been served, nice and promptly; exactly what I was hoping for.

Making NHibernate Behave

The recommended way or using NHibernate with MVC is to have a single session created per request. That is each time a client makes a request for a page, a new session is opened and kept open until the request is complete and data is returned to the client.

Sounds a little like the RequestBehaviour activation type fits perfectly here doesn't it?

To test this, we need to setup NHibernate and create a simple user class and repository. So to start, here's how I like to get my session factory:
namespace DITest
{
public static class SessionFactoryProvider
{
private static ISessionFactory sessionFactory;
private static Object lockObj = new Object();

private static void BuildSessionFactory()
{
string connStr = ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString;

sessionFactory = Fluently.Configure().
Database(MsSqlConfiguration.MsSql2005.ConnectionString(connStr)).
ExposeConfiguration(c => c.Properties.Add("hbm2ddl.keywords", "none")).
Mappings(m => m.FluentMappings.AddFromAssemblyOf()).
BuildSessionFactory();
}

public static ISession OpenSession()
{
if (sessionFactory == null)
lock(lockObj)
if (sessionFactory == null)
BuildSessionFactory();

return sessionFactory.OpenSession();
}
}
}

And this is registered with Ninject like so:
Bind().ToMethod(x => SessionFactoryProvider.OpenSession()).InRequestScope();

Next, a simple user class, mapping (I'm using FluentNhibernate here to do the mapping) and repository (all in one place for brevity):
namespace DITest
{
public class User
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual int Age { get; set; }
}

public class UserMap : ClassMap
{
public UserMap()
{
Id(c => c.Id);
Map(c => c.Name);
Map(c => c.Age);
}
}

public class UserRepository
{
ISession session;
private IQueryable Users
{
get { return session.Query(); }
}

public UserRepository(ISession session)
{
this.session = session;
}

public IList GetUsers()
{
using (session.BeginTransaction())
{
var query = from c in Users select c;
return query.ToList();
}
}
}
}

Finally, updated the controller to pull some information from the database:
public class HomeController : Controller
{
UserRepository repo;
public HomeController(UserRepository userRepo)
{
repo = userRepo;
}

public ActionResult Index()
{
ViewBag.Users = repo.GetUsers();
return View();
}
}

To verify this was all working correctly and the session is being closed properly, I setup logging to log debug information, which churns out tons of useful information:






Then after running up the page and doing a request, we can look at the generated log and see what's been happening:
14/07/11 12:42:50 DEBUG [session-id=6bf6823c-44d1-4a15-888e-c858a9212024] opened session at timestamp: 634462405708, for session factory: [/b9e13234ae244e18b7f2ce1923c58e48]
14/07/11 12:42:50 DEBUG Begin (Unspecified)
14/07/11 12:42:50 DEBUG Obtaining IDbConnection from Driver
...//edited for brevity
14/07/11 12:42:50 DEBUG IDbTransaction disposed.
14/07/11 12:42:50 DEBUG transaction completion
14/07/11 12:42:50 DEBUG aggressively releasing database connection
14/07/11 12:42:50 DEBUG Closing connection
14/07/11 12:42:50 DEBUG [session-id=6bf6823c-44d1-4a15-888e-c858a9212024] running ISession.Dispose()
14/07/11 12:42:50 DEBUG [session-id=6bf6823c-44d1-4a15-888e-c858a9212024] executing real Dispose(True)
14/07/11 12:42:50 DEBUG closing session
14/07/11 12:42:50 DEBUG running BatcherImpl.Dispose(true)

I've cut out a lot of the logging that just details queries are happening so that we can see what we care about; that the session is being closed properly after the requests have happened, and not before!

Summary

We looked at the various types of activation behaviour that Ninject supports, delved deeper into RequestBehaviour and verified that it is in fact doing what it says on the tin, and then saw how this is useful when working with MVC and NHibernate.

So now we have an NHibernate session that will last for the duration of a request. What would be really useful now is some concept of a unit of work, to allow multiple Nhibernate requests to be batched into a single transaction. Stay tuned!

Ninject And ASP .Net MVC3

I've mentioned Ninject before, it's an excellent dependancy injection framework that lets you keep your code loosely coupled.

I've also mentioned that I've been working with the MVC Framework quite a lot of late, and what's neat is that hooks are provided that make it easy to use your own dependancy injection framework. To that end, this post will be looking at how Ninject can be integrated with MVC3, and why that's awesome!

I'll be working with a clean MVC3 project created in Visual Studio 2010. There are a couple of ways of integrating Ninject; using the IDependancyResolver interface, or inheriting from NinjectHttpApplication.

Option 1: IDependancyResolver

All we need to do here is implement IDependancyResolver and then register an instance of it on application startup.

So a simple implementation for Ninject will look something like this:
using System;
using System.Web.Mvc;
using System.Collections.Generic;
using Ninject;
using Ninject.Modules;

public class NinjectResolver : IDependencyResolver
{
IKernel kernel;

public NinjectResolver(INinjectModule[] modules)
{
kernel = new StandardKernel(modules);
}

public object GetService(Type serviceType)
{
return kernel.Get(serviceType);
}

public IEnumerable GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
}

And we register this in Application_Start with a simple call like so:
var resolver = new NinjectResolver(new MyModule());
DependencyResolver.SetResolver(resolver);

MVC3 will then use this object when trying to instantiate an instance of a class, but will fall back to it's built in methods for locating objects if this fails. What this means in practice is that you don't need to worry about registering all of the default objects MVC3 uses such as the controller factory, leaving you free to just deal with the stuff you care about.

Option 2: NinjectHttpApplication

The second option is to make use of Ninject's MVC3 extension which can be found here.

In this case, all we need to do is change our MvcApplication class (found in Global.asax) to inherit from NinjectHttpApplication instead of MvcApplication, and then implement CreateKernel to register the modules we've created.

public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

}

protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

public override IKernel CreateKernel()
{
return new StandardKernel(new MyModule());
}
}

And that's it; now Ninject will be used to resolve any dependencies that are requested when the object model is being built.

Which Approach?

But which of the two approaches should you use? It doesn't matter hugely, the first option allows for a very quick integration, you could even register a dependency resolver in a much more concise fashion making use of lambdas like so:
var kernel = new StandardKernel(modules);
DependencyResolver.SetResolver(
t => {
try { return kernel.Get(t); }
catch { return null; }
},
t => kernel.GetAll(t)
);

However, using Ninject's MVC3 extension is marginally more self contained, so I tend to prefer making use of NinjectHttpApplication instead. Note that Ninject will still find the right controllers without registering them, so there is no need to register all your controllers unless you want to add additional configuration to them.

If you think you're likely to want to change your DI framework, then it would make more sense to make use of the IDependancyResolver interface so that you can drop in a quick replacement, although personally I think that scenario is somewhat unlikely.

Now you're loosely coupled

So that's a couple of simple ways to integrate Ninject with MVC3; not too hard to achieve and provides a lot of power and flexibility.

Jquery Auto-Complete with ASP .Net MVC

I've been doing a lot of work with Microsoft's MVC Framework over the past few weeks, having been a convert to the MVC way of doing things for some time.

A customer requested a feature to select an item using a popup form that would allow the user to search and select the relevant entry. I decided this could be achieved in a less obtrusive manner by using an auto-complete field a la google suggest.

Google Auto Complete

The Jquery UI library features a number of useful UI elements, with an auto-complete widget among them, so this is what I decided to use.

The MVC Controller

We'll start off implementing the backend, which will be an action in a controller that will return a JSON result.

public ActionResult Customers(string term)
{
List list = new List{
new Customer(){AccountName = "Test Company 1", AccountNum = "1234"},
new Customer(){AccountName = "Another Test 2", AccountNum = "1235"},
new Customer(){AccountName = "Another Company 3", AccountNum = "1236"},
new Customer(){AccountName = "Testing Account 4", AccountNum = "1237"},
new Customer(){AccountName = "Late Company", AccountNum = "1238"},
new Customer(){AccountName = "Test Company", AccountNum = "1239"},
};
return Json(list.Where(c => c.AccountName.Contains(term)));
}

In this case I'm just putting together a list of mock data and returning it as a JSON result using MVC's built in Json encoding functionality.

The only other thing to note here is the function argument term which contains the search term that will be entered into the auto-complete box. This is what will be used to filter our data.

Obviously in an actual implementation we'd be calling out to our data access layer to do the querying, but for the sake of example I'll be keeping this simple.

Jquery UI

Now that we have some data to work with, let's pull it down and display it. First the HTML:

And then the JavaScript:
$(document).ready(function() {
$('#customer_search').autocomplete({
source:'/POD/Customers',
minLength: 3,
select : function(event, ui){
$( "#customer_search" ).val( ui.item.AccountName );
//here we might want to store ui.item.AccountNum etc...
return false;
},
focus: function( event, ui ) {
$( "#customer_search" ).val( ui.item.AccountName );
return false;
},
}).data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "

  • " )
    .data( "item.autocomplete", item )
    .append( "" + item.AccountName + " (" + item.AccountNum + ")" + "" )
    .appendTo( ul );
    };
    });

    The important things to note here:

    • Select Function: We're setting the select function to allow us to handle what happens when the user selects an item ourselves. Returning false prevents the default handler from running.
    • Focus function: As above, we're handling focus ourselves so that we can display the custom data field of our choosing. By default the 'value' property would be used.
    • Render Item: We're overriding this to give us control over how data is presented in the drop down list that is shown whilst searching. Again this allows us to display custom data fields, rather than the default 'value' field that the auto-complete field expects.

    You should end up with something like this:

    Summary

    So there we have it, a simple example of how to hook up Jquery auto-suggest to an ASP .Net MVC controller with custom data. Enjoy!