Nik's Technology Blog

Travels through programming, networks, and computers

Upgrading an MVC Project to Bootstrap as a Side Project

We have an existing ASP.NET MVC project which has grown to the point where making the switch to use the Bootstrap framework required a substantial amount of work to the Views. Unfortunately this isn't high priority so we couldn't afford to do this in one go, instead we had to find a solution which would enable us to deploy the solution into production using the old Views and Layouts to introduce new functionality to the solution mid-way through the Bootstrap conversion.

To overcome this problem and allow us to upgrade to Bootstrap as a side project we needed a clever solution to effectively allow us to switch from Bootstrap to the old Views and Layout quickly and easily, and then back again.

This was our solution to the problem:

  1. We created a Bootstrap MVC _Layout and added it to the solution.
  2. We created an ActionFilterAttribute class called UseBootstrapLayout which we used to decorate the Actions to denote which Layout the Action method should use to render the View.
  3. We copied each View we were going to upgrade to Bootstrap and named it the same but appended a 2 at the end of the filename.
  4. In _ViewStart.chtml we added to code (below) to check if the View ended with a 2 and which allowed us to switch to the Bootstrap Layout if it did.

If we needed to deploy the application before the Bootstrap update was complete we simply changed to _ViewStart.chtml code to use the old _Layout. All the rest of the code changes and new Views could stay the same.

    /// <summary>
    /// Method to change a view name used by an action method.
    /// We are using this to enable us to re-skin the system
    /// </summary>

public class UseBootstrapLayout : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.RouteData.Values["action"] = filterContext.RouteData.Values["action"] + "2";
        }
    }

@{

    // _ViewStart.chtml
    var view = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString();

    string layout = "";
    if (view.EndsWith("2"))
    {
        layout = "~/Views/Shared/NewBootstrapLayout.cshtml";
    }
    else
    {
        layout = "~/Views/Shared/_Layout.cshtml";
    }

    Layout = layout;
}

    [UseBootstrapLayout]
    [HttpGet]
    public ActionResult Index()
    {
    return this.View();
    }

No defining declaration found for implementing OnValidate(System.Data.Linq.ChangeAction)

If you happen to be getting an error message like the one below, then read on.

Error    1    No defining declaration found for implementing declaration of partial method 'mvcCMS.Models.WebPage.OnValidate(System.Data.Linq.ChangeAction)'    C:\mvcCMS\Models\WebPage.cs    28    22    mvcCMS


I'm using LINQ to SQL designer in Visual Studio to create a database schema and I'm using a partial class to extend the code generated by the designer.

In the example below I am using the pattern used by NerdDinner.com to add business rules/validation to the model classes LINQ to SQL built based on my database schema.

namespace mvcCMS.Models
{
    public partial class WebPage
    {
        public bool IsValid
        {
            get { return (GetRuleViolations().Count() == 0); }
        }
        public IEnumerable<RuleViolation> GetRuleViolations()
        {
            if (String.IsNullOrEmpty(Title))
                yield return new RuleViolation("Title is required", "Title");
            if (String.IsNullOrEmpty(Text))
                yield return new RuleViolation("Web copy is required", "Text");

            yield break;
        }
        partial void OnValidate(ChangeAction action)
        {
            if (!IsValid)
                throw new ApplicationException("Rule violations prevent saving");
        }
    }
}

Where OnValidate() is a partial method LINQ to SQL provides which enables us to be notified when the object is about to be persisted to the database, so we can check all our business rules have been met before the object is flushed to the database.

An empty OnValidate() method is part of the designer generated code for your data class located in the #region Extensibility Method Definitions and it seems that these Extensibility Method Definitions only get added to the designer code when your tables have primary keys.

When a table is dragged onto the Object Relational Designer in Visual Studio the classes that are generated will only implement INotifyPropertyChanging and INotifyPropertyChanged if your tables have primary keys.  If the classes don't implement these interfaces the code won't implement the OnValidate() method, and if the OnValidate() method doesn't exist your partial class won't compile.

The Solution

The solution is simple.  Add a primary key to your database table, delete the associated data class from the Object Relational Designer and then drag the database table from Server Explorer back onto the Object Relational Designer surface.

You should then find the designer generated code now implements INotifyPropertyChanging and INotifyPropertyChanged and the class contains a definition for OnValidate() in the #region Extensibility Method Definitions.  Your code should now compile.

Setting Up ASP.NET MVC with NUnit for Visual Studio 2008 Standard Edition &amp; Visual Web Developer Express 2008

I've just spent my lunch hour downloading and installing ASP.NET MVC.  I also downloaded the sample chapter from Professional ASP.NET MVC 1.0 (large PDF) which walks through the development of NerdDinner.com.  I began to create a test ASP.NET MVC project on Visual Studio 2008 Standard.

One of the main positives of ASP.NET MVC is that Test Driven Development is so much easier than with ASP.NET Webforms.

I soon realised when I created my first ASP.NET MVC project however that unless you have Visual Studio Professional or higher you don't get Visual Studio test Unit Framework, which means that to create a test project, you first need to install another testing framework such as NUnit, and configure Visual Studio or Visual Web Developer 2008 to use it.

This is an extract from the book Professional ASP.NET MVC 1.0:

Note: The Visual Studio Unit Test Framework is only available with Visual Studio 2008 Professional and
higher versions). If you are using VS 2008 Standard Edition or Visual Web Developer 2008 Express you
will need to download and install the NUnit, MBUnit or XUnit extensions for ASP.NET MVC in order for
this dialog to be shown. The dialog will not display if there aren't any test frameworks installed.

I already had NUnit installed, so I began my search for an NUnit extension for ASP.NET MVC, which I found here. Updated NUnit Templates for ASP.Net MVC 1.0 RTM

After running installNUnit.cmd which created the registry entries required by Visual Studio, you need to make sure the registry entries created point to the compressed templates.

Note: If you are using Visual Web Developer 2008, this might be all you need to do.  Click on File > New Project and check to see if "Test" appears under "Project types" on the left-hand menu in the dialogue box.  If not carry on reading.

Copy the NUnit test templates from the downloaded directory (in your chosen .NET language) MvcApplication.NUnit.Tests.zip to the following folder on your machine:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Test

or here for VWD 2008:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\VWDExpress\ProjectTemplates\CSharp\Test

Then make sure the registry entry here:

HKEY_LOCAL_MACHINE\SOFTWARE\VisualStudio\9.0\MVC\TestProjectTemplates\NUnit\C#

or here for VWD 2008:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VWDExpress\9.0\MVC\TestProjectTemplates\NUnit\C#

Correctly points to the location of MvcApplication.NUnit.Tests.zip. e.g.

Path: CSharp\Test\

Template: MvcApplication.NUnit.Tests.zip

Then close all instances of Visual Studio and open up the command prompt and move to the following location:

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE>

and run the following command:

> devenv /setup

Once this has completed, you should find that when you create an ASP.NET MVC project, you will now get another pop-up menu asking you if you wish to create a unit test project for your application using NUnit.