ASP.NET MVC3 app (part 1) – Entity Framework and code first

How often you need to have cascading choices on UI in order to make your application user friendly? In my experience, almost every modern application has some form of hierarchy, and that is where cascading dropdowns are used. But, I want to make this less repetitive and more elegant. So, let’s begin. In first part (this) I will create an simple web app using entity framework code-first and make simple model which will be used for creating this functionality. It is one speedy run-through of new features, without advanced topics, so mind some bad practices, this blog post is not about good programming, first part is for MVC3/.NET 4 beginners with experience with older versions of MVC and .NET.

It will be an mvc3 razor internet application:

image

With latest MVC tools update there are already almost all necessary NuGet packages installed in new project:

image

I will just update all of jQuery packages as they have updates at the moment, and add EntityFramework.SqlServerCompact (NuGet will add dependencies), so SQL server won’t be needed.

As this is demo app, I will put everything into single project. It will be an product catalogue.

This is data model:

image

Central object will be product model (I will use vehicles domain), which has type, version, trim level and manufacturer. Simple enough. Objects on diagram are simple POCO objects with collection properties marked as virtual, so entity framework can override them and inject DynamicProxy objects for lazy loading.

This will be my repository:

image

For this DbContext to work, I need to do one more thing – to put connection string into my web.config:

image

As I don’t want to create test data every time I change my model, I can use database initializer class to create test data (this is useful for unit testing):

image

And this is it. I now have database and data. Actually, I will have it when I start my application, if I add this to global.asax:

image

To test this, I will use controller autoscaffold feature of new MVC tools update:

image

This will autocreate controller and all views Smile. After this action, starting app and visiting http://localhost:57095/Manufacturer will give:

image

Note that only manufacturers for which I created Models are in database. This is because I only added Models, and EF added all related objects, and BMW was not among them.

Using auto scaffold I created controllers for all model objects in couple of minutes.

This is end of part 1, I now have application which will I use to create unobtrusive cascading dropdowns. In the next part I will make cascading dropdown loading using standard methods (jQuery and ajax).

For more info about EF Code First, visit

http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx

and

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

UPDATE: Added part 2

Fix selected tab in SharePoint top links menu

Fastest way to accomplish this is to use jquery! 🙂

function fixTabs(){
    $.each($(".customNavTabActive"), function() {
        $(this).removeClass("customNavTabActive");
        $(this).parentsUntil("table").each(function() {
            $(this).removeClass("customNavTabActive");
        });
    });
    $.each($("a.customNavTab"), function() {
        if (this.href == document.location.href || this.href + "/default.aspx" == document.location.href) {
            $(this).parent("td").addClass("customNavTabActive");
        }
    });
}

Update: I have improved this code a little bit 🙂

function fixTabs(){
    var normalNavTavCss = "customNavTab";
    var firstCellActiveCss = "customNavTabActive";
    var firstCellCss = "customNavTab";
    var lastCellActiveCss = "customNavTabActive";
    var lastCellCss = "customNavTab";
    var cellActiveCss = "customNavTabActive";
    $.each($("." + cellActiveCss), function() {
        $(this).removeClass(cellActiveCss);
        $(this).parentsUntil("table").each(function() {
        $(this).removeClass(cellActiveCss);
        });
    });
    var lastCell;
    var lastCellSelected;
    $.each($("." + normalNavTavCss + " a"), function(i) {
        lastCell = $(this).parent("td");
        var location = document.location.href.replace("/default.aspx", "");
        var link = this.href.replace("/default.aspx", "");
        lastCellSelected = (link == location || location.indexOf(link) > -1);
        if (lastCellSelected) {
            if (i == 0) {
                lastCell.addClass(firstCellActiveCss);
            }
            else {
                lastCell.addClass(cellActiveCss);
            }
        }
        else if (i == 0) {
            lastCell.addClass(firstCellCss);
        }
    });
    if (lastCellSelected) {
        lastCell.removeClass(cellActiveCss);
        lastCell.removeClass(firstCellActiveCss);
        lastCell.addClass(lastCellActiveCss);
    }
    else {
        lastCell.addClass(lastCellCss);
    }
}