Introduction to EntityFramework 6 Part 3: CRUD operations

Introduction

In the previous post we’ve got as far as generating our database and the Cars and user management tables. It’s time to add, delete and edit Car objects using the built-in capabilities of MVC 5.

Open the project we’ve been working on so far and let’s get to it!

Demo

We’ll create our Cars controller first. Right-click the Controllers folder of the Web layer, select Add, Controller… The Add Scaffold window will open. Select the following option:

MVC 5 Controller with views, using Entity Framework

Click Add and fill in the Add Controller dialog as follows:

Create scaffolding for Cars with Entity Framework

We want to base our controller and views on the Car object. The correct DB context to use is the CarsDbContext we created previously. Leave all other options untouched so that even the views will be created. The scaffolding engine will produce some boilerplate code as a starting point. It creates a lot of stuff for us actually: all the controller actions and views necessary to add, edit and delete Car objects. Check the Views folder. There’s a new folder in there called Cars with 5 cshtml files following the default view names: create, delete etc.

In reality you’ll almost always modify the controller code such as putting the following instantiation in a Repository and letting the controller reference it through an abstraction:

private CarsDbContext db = new CarsDbContext();

If you don’t know what’s wrong with putting this piece of code directly in a controller then check out the series on SOLID and loosely coupled layered design with DDD. However, this series is – almost – purely technical so it’s up to you to organise your code as you wish.

Now that we have the user management tables in place we can take advantage of them. We want to restrict access to the Car views to authorised users. Add the Authorize attribute to the controller:

[Authorize]
public class CarsController : Controller

If you’d like to know more about authentication and access control in MVC 5 checkout the series on Identity here.

For easy access open _Layout.cshtml in the Views/Shared folder and locate the following code which generates the code:

<ul class="nav navbar-nav">
         <li>@Html.ActionLink("Home", "Index", "Home")</li>
         <li>@Html.ActionLink("About", "About", "Home")</li>
         <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

Add another ActionLink to open the Cars Index view:

<li>@Html.ActionLink("Cars", "Index", "Cars")</li>

Run the application, click the Cars link and you’ll be directed to the login page. There’s a link to register new users. Click on it a register yourself with the application. If all goes well then your registration will succeed and you’ll see “Hello ” + your username in the upper right-hand corner of the view. Click the Cars link again and you’ll get to an empty page:

Empty Cars list after initial run of application

Click the Create New link. You’ll directed to a simple page to add new Cars:

Default create car view generated by MVC 5

The text field for the Make property is OK for demo purposes. In reality we might need to pick the Make from a drop-down list so that we don’t end up with values like Ford, ford, FORD in the database. However, the text field for the category is completely off. We’d like to use the enumeration values in here. We don’t want to allow the users to type in just any category. The reason is that the scaffolding engine created the following code to render a field for the category in Create.cshtml:

@Html.EditorFor(model => model.Category)

It didn’t know how to render an editor for an enum so the best approximation was a text field. You probably agree that this is not OK. So we’ll need to digress a little from our main discussion on Entity Framework and do some other work before we resume: we’ll create a new template.

Add a folder called EditorTemplates within the Views/Shared folder so that the new template will be available for all views. Right-click this new folder and select Add, View… as editors are simply partial views. We need to be careful with the naming of the custom editor for the car category. We need to set it to the type of the Category property which is CarCategory. This is how the Razor engine will find the correct partial template. In case the property type is ‘int’ it will go look for a partial editor view called ‘int’. So in the View name field type in “CarCategory” and select the “Create as a partial view” option. You’ll get an empty file called CarCategory.cshtml.

We’ll need to get hold of the values in the CarCategory enumeration. Also, we want to make sure that if someone extends the enumeration then the drop down list Category editor will automatically pick up the new value. We’ll build an extension method that returns a sequence of SelectListItems based on the enumeration values.

Add a new folder called Extensions to the Web layer. Insert a class called EnumExtensions into that folder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Cars.Web
{
    public static class EnumExtensions
    {
        public static IEnumerable<SelectListItem> GetItemsAsSelectListItems(this Type type
            , int? selectedItem)
        {
            if (!typeof(Enum).IsAssignableFrom(type))
            {
                throw new ArgumentException("You must pass in an enum type.");
            }

            string[] names = Enum.GetNames(type);
            IEnumerable<int> values = Enum.GetValues(type).Cast<int>();

            return names.Zip(values, (n, v) =>
                new SelectListItem() {Text = n, Value = v.ToString(), Selected = v == selectedItem });
        }
    }
}

Make sure you modify the namespace to Cars.Web so that the extension method becomes available throughout the Web project without having to import a namespace.

In short we do the following in this code:

  • We check if the type is an enum. If it’s not, then an exception is thrown
  • We extract the names and integer values from the enum, such as Family=1,Sports=2 etc
  • We use the Zip LINQ operator to join the names and values into one sequence and build a list of SelectListItems
  • The selectedItem parameter will be used to set the originally saved category as the selected item. Without this check the saved category won’t be selected when updating a Car

If you’re not sure of the usage of the Zip operator, check its documentation here.

CarCategory.cshtml will have the following code:

@using Cars.Domain

@{
    var selectListItems = typeof(CarCategory).GetItemsAsSelectListItems((int?)Model);
}

@Html.DropDownList("", selectListItems)

You are probably wondering what this Model is. These templates also have Model properties like normal views. The Model in this case will be the object that the template is operating on, i.e. CarCategory which can be converted into a nullable int. The CarCategory will be set when editing a Car, hence the need for a nullable value.

Run the application, navigate to Cars, log in and click the Create New link. The car types should show up correctly in the drop down list. Add a couple of new cars. Each time you’ll be redirected to the Cars Index page with the updated list of cars:

New car objects inserted into database

Test the Edit link. You should see that the category is correctly selected in the drop down list.

Then play around with the other links, i.e. Details and Delete. They should work just fine. You can even check the database to see how the cars are stored:

Car objects shown in database

In the next part of this series we’ll look at the new asynchronous language features and logging in EF.

You can view all posts related to data storage on this blog here.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: