I have been writing about Entity Framework Core ( EF Core ) lately and how to integrate it with .NET Core. If you are interested in learning how to use EF Core in a .NET Core Console Application, you may be interested in my article Getting Started with Entity Framework Core and SQLite. I then showed how to use EF Core Migrations to manage the SQLite database in the article EF Core Migrations Tutorial.

In this article I will be showing how to use EF Core with ASP.NET Core MVC to display a list of reminders in a SQLite database. I will be using EF Core Migrations to create the database. I will also be using Dependency Injection in ASP.NET Core with a custom DbContext Class in Entity Framework Core.

All of this code is written by hand using Visual Studio Code on macOS.

New ASP.NET Core MVC Project

In a terminal window on macOS, I create a new mvcdata directory and .NET Core Application and open the files in Visual Studio Code.

mkdir mvcdata
cd mvcdata

dotnet new
dotnet restore

code.

I need to install a few dependencies in this project. At a minimum I need the Kestrel Server to serve my ASP.NET Core MVC pages and, of course, I need ASP.NET Core MVC (Microsoft.AspNetCore.Server.Kestrel and Microsoft.AspNetCore.Mvc).

I will be using EF Core with SQLite as well as the EF Core Tools for database migrations, so I also add Microsoft.EntityFrameworkCore.Design, Microsoft.EntityFrameworkCore.Sqlite, and Microsoft.EntityFrameworkCore.Tools.

Since I am writing this from scratch in Visual Studio Code, it also helps to add a developer exception page in the ASP.NET Core Pipeline. Therefore I will also be using Microsoft.AspNetCore.Diagnostics in the application.

And finally, I set preserveCompilationContext to true in the build options for use with the Razor View Engine. My project.json is as follows:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },
  "dependencies": {
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.EntityFrameworkCore.Design": "1.0.0-*",
    "Microsoft.EntityFrameworkCore.Sqlite": "1.0.0"
  },
  "tools": {
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-*"
  },
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      },
      "imports": "dnxcore50"
    }
  }
}

Configure ASP.NET Core MVC

I wire up Kestrel to serve my web pages as well as add the ASP.NET Core MVC Middleware. If this is totally new to you, I recommend reading my ASP.NET Core MVC From Scratch Article that walks through this information in more detail.

using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace MvcData {
    public class Program {
        public static void Main(string[] args) {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using MvcData.Models;
using MvcData.Services;

namespace MvcData {
    public class Startup {
        public void ConfigureServices(IServiceCollection services) {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app) {
            app.UseMvcWithDefaultRoute();
        }
    }
}

I will be adding more to the Startup Class in a minute. This is the bare minimum to get ASP.NET Core MVC up and running. The Startup Class is the entry point into my ASP.NET Core Applications. I am adding ASP.NET Core MVC to the Dependency Injection Framework and its middleware to the pipeline. I could configure it to use custom routes, but for this example I will just use the ASP.NET Core MVC Default Routing.

Developer Exception Page in ASP.NET Core

As I mentioned earlier, I don't always get these sample applications right the first time. Adding logging would be overkill, but the developer exception page is a necessity for displaying exceptions that occur in the pipeline. I add this to the middleware pipeline in the Configure Method of the Startup Class before ASP.NET Core MVC.

public void Configure(IApplicationBuilder app) {
    app.UseDeveloperExceptionPage();
    app.UseMvcWithDefaultRoute();
}

Adding Entity Framework Core

I add a custom DbContext, called MyDbContext, as well as a custom entity, called Reminder, to save reminders in my ASP.NET Core MVC Web Application.

using Microsoft.EntityFrameworkCore;

namespace MvcData.Models {
    public class MyDbContext : DbContext {
        public DbSet<Reminder> Reminders { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            optionsBuilder.UseSqlite("Filename=./db.sqlite");
        }
    }
}
using System.ComponentModel.DataAnnotations;

namespace MvcData.Models {
    public class Reminder {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Title { get; set;}
    }
}

I am using System.ComponentModel.DataAnnotations to give Entity Framework Core a bit more information about the properties on my Reminder Class. The property, Id, will be the primary key in the SQLite Database and the Title Column associated with the Title Property is required and should be set to non-nullable. The primary key would have been picked up using Entity Framework Core conventions, but I thought I would make it explicit anyway.

I am wrapping the use of MyDbContext into a service, called MyData, for a bit more abstraction. This is a bit overkill for this example, but in larger projects one may want to limit the surface area of Entity Framework Core.

using System.Collections.Generic;
using System.Linq;
using MvcData.Models;

namespace MvcData.Services {
    public interface IMyData {
        List<Reminder> FetchReminders();
    }

    public class MyData : IMyData {
        private readonly MyDbContext _db;

        public MyData(MyDbContext db) {
            _db = db;
        }

        public List<Reminder> FetchReminders() {
            return _db.Reminders.ToList();
        }
    }
}

As I will explain in a moment, dependency injection in ASP.NET Core will inject MyDbContext into the MyData Service.

ASP.NET Core Dependency Injection

ASP.NET Core will inject my custom DbContext, called MyDbContext, into the MyData service in my ASP.NET Core Web Application. Again, dependency injection in ASP.NET Core happens in the Startup Class so I will add it there. I also register MyData with the dependency injection framework, because it will be injected into my RemindersController. The final Startup Class wiring up dependency injection, ASP.NET Core MVC, and a developer exception page looks as follows:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using MvcData.Models;
using MvcData.Services;

namespace MvcData {
    public class Startup {
        public void ConfigureServices(IServiceCollection services) {
            services.AddMvc();
            services.AddDbContext<MyDbContext>();
            services.AddTransient<IMyData,MyData>();
        }

        public void Configure(IApplicationBuilder app) {
            app.UseDeveloperExceptionPage();
            app.UseMvcWithDefaultRoute();
        }
    }
}

ASP.NET Core MVC Controller and Views

Now that the ASP.NET Core Middleware Pipeline is set-up and configured, I can create ASP.NET Core MVC Controllers and Views. The Index Action of the RemindersController will retrieve a list of reminders in the SQLite Database via Entity Framework Core and display the reminders in an unordered list.

using Microsoft.AspNetCore.Mvc;
using MvcData.Services;

public class RemindersController : Controller {
    private readonly IMyData _myData;

    public RemindersController(IMyData myData) {
        _myData = myData;
    }
    public IActionResult Index() {
        var reminders = _myData.FetchReminders();
        return View(reminders);
    }
}
@model List<Reminder>
@using MvcData.Models
<ul>
@foreach(var reminder in Model) {
    <li>@reminder.Title</li>
}
</ul>

EF Core Migrations to Create SQLite Database

The ASP.NET Core Web Application will not run without the SQLite Database. I can create it using EF Core Migrations. See my EF Core Migrations Tutorial for more detail on using migrations. From a Terminal Window in Visual Studio Code I run the Entity Framework Core Tools commands that create the initial migration and database. I also manually populated a couple of reminders into the SQLite Database for testing purposes.

dotnet ef migrations add InitialMigration

dotnet ef database update

Run the ASP.NET Core MVC Web Application

Run the ASP.NET Core MVC Web Application and display the results in a browser.

dotnet run
Project mvcdata (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Hosting environment: Production
Content root path: /Users/Sasquatch/Core/mvcdata
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

ASP.NET Core MVC Web Application with EF Core

Conclusion

If you are learning ASP.NET Core MVC, I hope you found the tutorial useful. I wrote this simple tutorial using Visual Studio Code on macOS so it seems like a great deal of configuration, but if you use Visual Studio 2015 a lot of this is done for you. I like to create these samples from scratch using a simple editor, because it gives me a better understanding of all the nitty gritty details.

You can find me on twitter as Koder Dojo. I hope to hear from you! Best Wishes!

Posted by Koder Dojo

Hi! I am a freelance C#, ASP.NET MVC Web Developer learning both Python and ASP.NET Core MVC. This website is a fun playground for me to write about the new and exciting things I am learning. I think of it as a daily journal of my adventures that 1) helps reinforce what I am learning by writing about it, and 2) hopefully helps and inspires others during their learning. Many of the examples are based on exercises and problem sets in my online courses. I am always eager to meet new people who are passionate about learning, too, so please connect with me on twitter. I am @KoderDojo. Best Wishes!

Related Posts: