By Leonardo Esposito

Dino Esposito is the author of “Programming ASP.NET MVC” for Microsoft Press as well as “Programming ASP.NET 4” and other bestselling books such as “Microsoft ® .NET: Architecting Applications for the Enterprise”. Regular contributor to MSDN Magazine and DevProConnections Magazine, Dino is a frequent speaker at industry events all over the world including Microsoft TechED and DevConnections. After a decade of Web development, Dino jumped on the mobile bandwagon and is actively developing for iOs, Android and WP7.

When you open up Visual Studio 2013 with the intent of building a new ASP.NET MVC 5 project, you find only one option: an ASP.NET Web Application. This is great, as it represents a moment of clarity in a whirlpool of similar-looking and confusing options. So you click and are presented with various options as to the type of project to create. You want ASP.NET MVC, right? So you pick up the MVC option. What you obtain is a no-op demo application that was probably meant to give you an idea of what it means to code for ASP.NET MVC. Even though the result does nothing, the resulting project is fairly overloaded.

You'll also find several Nuget packages and assemblies referenced that are not required by the sample application, yet are already there to save time for when you need them in action. This is not a bad idea in theory, as nearly any ASP.NET website ends up using jQuery, Bootstrap, Modernizr, Web Optimization, and others. And if you don't like it, you still have the option of starting with an empty project and adding MVC scaffolding. This is better, as it delivers a more nimble project even though there are many references that are useless at first. The truth is that any expert developer has his own favorite initial layout of the startup project, including must-have packages and scripts.

Although I may be tempted, I don't want to push my own ideal project layout on you. My purpose, instead, is applying the Occam's Razor to the ASP.NET MVC project templates that you get in Visual Studio 2013. I'll start with the organization of project folders and proceed through startup code, bundling, HTML layout, controllers, layers, HTTP endpoints, and multi-device views. Overall, here are ten good practices for sane ASP.NET MVC 5 development.

#1: Project Folders and Namespaces

Let's say you used the Visual Studio 2013 project template to create a new project. It works, but it's rather bloated. Figure 1 shows the list of unnecessary references detected by ReSharper.



Figure 1 : Unnecessary references in the ASP.NET MVC project built with the default Visual Studio 2013 template

It's even more interesting to look at the remaining references. Figure 2 shows what you really need to have referenced in order to run a nearly dummy ASP.NET MVC application.



Figure 2 : Strictly required assemblies in a basic ASP.NET MVC 5 project

Here's the minimal collection of Nuget packages you need in ASP.NET MVC.

<packages> <package id="Microsoft.AspNet.Mvc" version="5.0.0" targetFramework="net45" /> <package id="Microsoft.AspNet.Razor" version="3.0.0" targetFramework="net45" /> <package id="Microsoft.AspNet.WebPages" version="3.0.0" targetFramework="net45" /> </packages>

The project contains the folders listed in Table 1.

When you start adding Nuget packages, some other conventions start appearing such as the Scripts folder for Modernizr and for jQuery and its plugins. You may also find a Content folder for Bootstrap style sheets and a separate Fonts folder for Bootstrap's glyph icons.

I find such a project structure rather confusing and usually manage to clean it up a little bit. For example, I like to place all content (images, style sheets, scripts, fonts) under the same folder. I also don't much like the name Models. (I don't like the name App_Start either but I'll return to that in a moment.) I sometimes rename Models to ViewModels and give it a structure similar to Views: one subfolder per controller. In really complex sites, I also do something even more sophisticated. The Models folder remains as is, except that two subfolders are addedLInput and View, as shown in Figure 3.



Figure 3 : Content and Models folder internal structure

Generally speaking, there are quite a few flavors of models. One is the collection of classes through which controllers receive data. Populated from the model binding layer, these classes are used as input parameters of controller methods. I collectively call them the input model and define them in the Input subfolder. Similarly, classes used to carry data into the Razor views collectively form the view model and are placed under the Models/View folder. Both input and view models are then split on a per-controller basis.

One more thing to note is the matching between project folders and namespaces. In ASP.NET it's a choice rather than an enforced rule. So you can freely decide to ignore it and still be happy, as I did for years. At some point - but it was several years ago - I realized that maintaining the same structure between namespaces and physical folders was making a lot of things easier. And when I figured out that code assistant tools were making renaming and moving classes as easy as click-and-confirm, well, I turned it into enforcement for any of my successive projects.

#2 Initial Configuration

A lot of Web applications need some initialization code that runs upon startup. This code is usually invoked explicitly from the Application_Start event handler. An interesting convention introduced with ASP.NET MVC 4 is the use of xxxConfig classes. Here's an example that configures MVC routes:

public class RouteConfig { public static void RegisterRoutes( RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }); } }

The code in global_asax looks like this:

RouteConfig.RegisterRoutes(RouteTable.Routes);

For consistency, you can use the same pattern to add your own classes that take care of application-specific initialization tasks. More often than not, initialization tasks populate some ASP.NET MVC internal dictionaries, such as the RouteTable.Routes dictionary of the last snippet (just after the heading for #2). For testability purposes, I highly recommend that xxxConfig methods are publicly callable methods that get system collections injected. As an example, here's how you can arrange unit tests on MVC routes.

[TestMethod] public void Test_If_Given_Route_Works() { // Arrange var routes = new RouteCollection(); MvcApplication.RegisterRoutes(routes); RouteData routeData = null; // Act & Assert whether the right route was found var expectedRoute = "{controller}/{action}/{id}"; routeData = GetRouteDataFor("~/product/id/123", routes); Assert.AreEqual(((Route) routeData.Route).Url, expectedRoute);}

Note that the code snippet doesn't include the full details of the code for custom GetRouteDataFor method. Anyway, the method uses a mocking framework to mock HttpContextBase and then invokes method GetRouteData on RouteCollection passing the mocked context.

var routeData = routes.GetRouteData(httpContextMock);

Many developers just don't like the underscore convention in the name of some ASP.NET folders, particularly the App_Start folder. Is it safe to rename this folder to something like Config? The answer is: it's generally safe but it actually depends on what you do in the project.

The possible sore point is the use of the WebActivator Nuget package in the project, either direct or through packages that have dependencies on it. WebActivator is a package specifically created to let other Nuget packages easily add startup and shutdown code to a Web application without making any direct changes to global.asax. WebActivator was created only for the purposes of making Nuget packages seamlessly extend existing Web applications. As WebActivator relies on an App_Start folder, renaming it may cause you some headaches if you extensively add/refresh Nuget packages that depend on WebActivator. Except for this, there are no problems in renaming App_Start to whatever you like most.

#3 Bundling and Minifying CSS Files

Too many requests from a single HTML page may cause significant delays and affect the overall time-to-last-byte metrics for a site. Bundling is therefore the process of grouping distinct resources such as CSS files into a single downloadable resource. In this way, multiple and logically distinct CSS files can be downloaded through a single HTTP request.

Minification, on the other hand, is the process that removes all unnecessary characters from a text-based resource without altering the expected functionality. Minification involves shortening identifiers, renaming functions, removing comments and white-space characters. In general, minification refers to removing everything that's been added mostly for readability purposes, including long descriptive member names.

Although bundling and minification can be applied together, they remain independent processes. On a production site, there's usually no reason not to bundle minified CSS and script files. The only exception is for large and very common resources that might be served through a Content Delivery Network (CDN). The jQuery library is a great example.

Bundling requires the Microsoft ASP.NET Web Optimization Framework available as a Nuget package. Downloading the Optimization Framework also adds a few more references to the project. In particular, they are WebGrease and Microsoft Infrastructure. These, in turn, bring their own dependencies for the final graph, shown in Figure 4.



Figure 4 : Graph of Nuget dependencies for bundling and minification

Bundles are created programmatically during the application startup in global.asax. Also in this case, you can use the xxxConfig pattern and add some BundlesConfig class to the App_Startup folder. The BundleConfig class contains at least one method with code very close to the following snippet.

public static void RegisterBundles( BundleCollection bundles) { bundles.Add(new StyleBundle("~/Content/Styles") .Include("~/Content/Styles/bootstrap.css", "~/Content/Styles/myapp.css")); }

The code creates a new bundle object for CSS content and populates it with distinct CSS files defined within the project. Note that the Include method refers to physical paths within the project where the source code to bundle is located. The argument passed to the StyleBundle class constructor instead is the public name of the bundle and the URL through which it will be retrieved from pages. There are quite a few ways to indicate the CSS files to bundle. In addition to listing them explicitly, you can use a wildcard expression:

bundles.Add(new Bundle("~/css") .Include("~/content/styles/*.css");

Once CSS bundles are defined invoking them is as easy as using the Styles object:

@Styles.Render("~/Bundles/Css")

As you can figure from the last two snippets, ASP.NET optimization extensions come with two flavors of bundle classes: the Bundle class and the StyleBundle class. The former only does bundling; the latter does both bundling and minification. Minification occurs through the services of an additional class. The default CSS minifier class is CssMinify and it is based on some logic packaged in WebGrease. Switching to a different minifier is easy too. All you do is using a different constructor on the StyleBundle class. You use the constructor with two arguments, the second of which is your own implementation of IBundleTransform.

#4 Bundling and Minifying Script Files

Bundling and minification apply to script files in much the same way as bundling and minifying CSS files. The only minor difference is that for frequently used script files (such as jQuery) you might want to use a CDN for even better performance. In operational terms, bundling and minifying script files requires the same process and logic as CSS files. You use the Bundle class if you're only concerned about packing multiple files together so that they are captured in a single download and cached on the client. Otherwise, if you also want minifying, you use the ScriptBundle class.

Like StyleBundle, ScriptBundle also features a constructor that accepts an IBundleTransform object as its second argument. This object is expected to bring in some custom logic for minifying script files. The default minifier comes from WebGrease and corresponds to the JsMinify class.

It's very common today to arrange very complex and graphically rich Web templates that are responsive to changes in the browser's window size and that update content on the client side through direct access to the local DOM. All this can happen if you have a lot of script files. It's not, for the most part, JavaScript code that you write yourself. It's general-purpose JavaScript that forms a framework or a library. In a nutshell, you often end up composing your client-side logic by sewing together multiple pieces, each of which represents a distinct download.

Considering the general recommendation of using as few script endpoints as possible - and bundling does help a lot in that regard - the optimal position of the