Add a model to a Razor Pages app in ASP.NET Core

By Rick Anderson

In this section, you add classes for managing movies in a database. You use these classes with Entity Framework Core (EF Core) to work with a database. EF Core is an object-relational mapping (ORM) framework that simplifies the data access code that you have to write.

The model classes you create are known as POCO classes (from "plain-old CLR objects") because they don't have any dependency on EF Core. They define the properties of the data that are stored in the database.

In this tutorial, you write the model classes first, and EF Core creates the database. An alternate approach not covered here is to generate model classes from an existing database.

View or download sample.

Add a data model

In Solution Explorer, right-click the RazorPagesMovie project > Add > New Folder. Name the folder Models.

Right click the Models folder. Select Add > Class. Name the class Movie and replace the contents of the Movie class with the following code:

using System;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

Scaffold the movie model

In this section, the movie model is scaffolded. That is, the scaffolding tool produces pages for Create, Read, Update, and Delete (CRUD) operations for the movie model.

Create a Pages/Movies folder:

  • In Solution Explorer, right click on the Pages folder > Add > New Folder.
  • Name the folder Movies

In Solution Explorer, right click on the Pages/Movies folder > Add > New Scaffolded Item.

Image from the previous instructions.

In the Add Scaffold dialog, select Razor Pages using Entity Framework (CRUD) > Add.

Image from the previous instructions.

Complete the Add Razor Pages using Entity Framework (CRUD) dialog:

  • In the Model class drop down, select Movie (RazorPagesMovie.Models).
  • In the Data context class row, select the + (plus) sign and accept the generated name RazorPagesMovie.Models.RazorPagesMovieContext.
  • Select Add.

Image from the previous instructions.

The scaffold process creates and updates the following files:

Files created

  • Pages/Movies: Create, Delete, Details, Edit, Index. These pages are detailed in the next tutorial.
  • Data/RazorPagesMovieContext.cs

File updated

  • Startup.cs: Changes to this file are detailed in the next section.
  • appsettings.json: The connection string used to connect to a local database is added.

Examine the context registered with dependency injection

ASP.NET Core is built with dependency injection. Services (such as the EF Core DB context) are registered with dependency injection during application startup. Components that require these services (such as Razor Pages) are provided these services via constructor parameters. The constructor code that gets a DB context instance is shown later in the tutorial.

The scaffolding tool automatically created a DB context and registered it with the dependency injection container.

Examine the Startup.ConfigureServices method. The highlighted line was added by the scaffolder:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddDbContext<RazorPagesMovieContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

The main class that coordinates EF Core functionality for a given data model is the DB context class. The data context is derived from Microsoft.EntityFrameworkCore.DbContext. The data context specifies which entities are included in the data model. In this project, the class is named RazorPagesMovieContext.

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
    public class RazorPagesMovieContext : DbContext
    {
        public RazorPagesMovieContext (DbContextOptions<RazorPagesMovieContext> options)
            : base(options)
        {
        }

        public DbSet<Movie> Movie { get; set; }
    }
}

The preceding code creates a DbSet<Movie> property for the entity set. In Entity Framework terminology, an entity set typically corresponds to a database table. An entity corresponds to a row in the table.

The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Perform initial migration

In this section, you use the Package Manager Console (PMC) to:

  • Add an initial migration.
  • Update the database with the initial migration.

From the Tools menu, select NuGet Package Manager > Package Manager Console.

PMC menu

In the PMC, enter the following commands:

Add-Migration Initial
Update-Database

Alternatively, the following .NET Core CLI commands can be used from the project folder:

dotnet ef migrations add Initial
dotnet ef database update

Ignore the following warning message, you fix that in a a later tutorial:

Microsoft.EntityFrameworkCore.Model.Validation[30000]
      No type was specified for the decimal column 'Price' on entity type 'Movie'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values using 'ForHasColumnType()'.

The Add-Migration command generates code to create the initial database schema. The schema is based on the model specified in the RazorPagesMovieContext (In the Data/RazorPagesMovieContext.cs file). The Initial argument is used to name the migrations. You can use any name, but by convention you choose a name that describes the migration. See Introduction to migrations for more information.

The Update-Database command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.

If you get the error:

SqlException: Cannot open database "RazorPagesMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

You missed the migrations step.

By Rick Anderson

In this section, you add classes for managing movies in a database. You use these classes with Entity Framework Core (EF Core) to work with a database. EF Core is an object-relational mapping (ORM) framework that simplifies the data access code that you have to write.

The model classes you create are known as POCO classes (from "plain-old CLR objects") because they don't have any dependency on EF Core. They define the properties of the data that are stored in the database.

In this tutorial, you write the model classes first, and EF Core creates the database. An alternate approach not covered here is to generate model classes from an existing database.

View or download sample.

Add a data model

In Solution Explorer, right-click the RazorPagesMovie project > Add > New Folder. Name the folder Models.

Right click the Models folder. Select Add > Class. Name the class Movie and add the following properties:

Add the following properties to the Movie class:

using System;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

The ID field is required by the database for the primary key.

Add a database context class

Add the following MovieContext.cs class to the Models folder:

using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie.Models
{
    public class MovieContext : DbContext
    {
        public MovieContext(DbContextOptions<MovieContext> options)
                : base(options)
        {
        }

        public DbSet<Movie> Movie { get; set; }
    }
}

The preceding code creates a DbSet property for the entity set. In Entity Framework terminology, an entity set typically corresponds to a database table, and an entity corresponds to a row in the table.

Add a database connection string

Add a connection string to the appsettings.json file.

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "ConnectionStrings": {
    "MovieContext": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Register the database context

Register the database context with the dependency injection container in the ConfigureServices method of the Startup class (Startup.cs):

public void ConfigureServices(IServiceCollection services)
{
    // requires 
    // using RazorPagesMovie.Models;
    // using Microsoft.EntityFrameworkCore;

    services.AddDbContext<MovieContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("MovieContext")));
    services.AddMvc();
}

Build the project to verify you don't have any errors.

Add scaffold tooling and perform initial migration

In this section, you use the Package Manager Console (PMC) to:

  • Add the Visual Studio web code generation package. This package is required to run the scaffolding engine.
  • Add an initial migration.
  • Update the database with the initial migration.

From the Tools menu, select NuGet Package Manager > Package Manager Console.

PMC menu

In the PMC, enter the following commands:

Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design -Version 2.0.3
Add-Migration Initial
Update-Database

Alternatively, the following .NET Core CLI commands can be used:

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet ef migrations add Initial
dotnet ef database update

Ignore the following message:

Microsoft.EntityFrameworkCore.Model.Validation[30000]
      No type was specified for the decimal column 'Price' on entity type 'Movie'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values using 'ForHasColumnType()'

You fix that in the next tutorial.

The Install-Package command installs the tooling required to run the scaffolding engine.

The Add-Migration command generates code to create the initial database schema. The schema is based on the model specified in the DbContext (In the Models/MovieContext.cs file). The Initial argument is used to name the migrations. You can use any name, but by convention you choose a name that describes the migration. See Introduction to migrations for more information.

The Update-Database command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.

Scaffold the Movie model

  • Run the following from the command line (in the project directory that contains the Program.cs, Startup.cs, and .csproj files):

    dotnet restore
    dotnet aspnet-codegenerator razorpage -m Movie -dc MovieContext -udl -outDir Pages\Movies --referenceScriptLibraries
    

If you get the error:

No executable found matching command "dotnet-aspnet-codegenerator"

The preceeding error happens when you are in the wrong directory. Open a command shell to the project directory (The directory that contains the Program.cs, Startup.cs, and .csproj files), and then run the preceeding command.

If you get the error:

The process cannot access the file 
'RazorPagesMovie/bin/Debug/netcoreapp2.0/RazorPagesMovie.dll' 
because it is being used by another process.

Exit Visual Studio and run the command again.

The following table details the ASP.NET Core code generators` parameters:

Parameter Description
-m The name of the model.
-dc The data context.
-udl Use the default layout.
-outDir The relative output folder path to create the views.
--referenceScriptLibraries Adds _ValidationScriptsPartial to Edit and Create pages

Use the h switch to get help on the aspnet-codegenerator razorpage command:

dotnet aspnet-codegenerator razorpage -h

Test the app

  • Run the app and append /Movies to the URL in the browser (http://localhost:port/movies).

  • Test the Create link.

    Create page

  • Test the Edit, Details, and Delete links.

If you get a SQL exception, verify you have run migrations and updated the database.

The next tutorial explains the files created by scaffolding.