Your First ASP.NET 5 Web App Using Visual Studio

By Erik Reitan

In this tutorial, you’ll create a simple web app using ASP.NET 5. The app stores data in a SQL database using Entity Framework (EF) and uses ASP.NET MVC to support the basic CRUD operations (create, read, update, delete).

In this article:

Prerequisites

Before you start, make sure that you have the followed the getting started steps for Installing ASP.NET 5 On Windows. This tutorial assumes you have already installed Visual Studio 2015 and the latest ASP.NET 5 runtime and tooling.

Note

For additional information about installing ASP.NET 5 on other platforms, see Getting Started.

Create a new ASP.NET 5 project

Start Visual Studio 2015. From the File menu, select New > Project.

Select the ASP.NET Web Application project template. It appears under Installed > Templates > Visual C# > Web. Name the project ContosoBooks and click OK.

../_images/02-new-project.png

In the New ASP.NET Project dialog, select Web Application under ASP.NET 5 Preview Templates. Also, make sure the Host in the cloud checkbox is not selected and click OK.

../_images/03-web-site-template.png

Running the default app

Once Visual Studio finishes creating the app, run the app by selecting Debug -> Start Debugging. As an alternative, you can press F5.

It may take time to initialize Visual Studio and the new app. Once it is complete, the browser will show the running app.

../_images/05-browser-runapp.png

After reviewing the running Web app, close the browser and click the “Stop Debugging” icon in the toolbar of Visual Studio to stop the app.

Review the project

In Visual Studio, the Solution Explorer window lets you manage files for the project. The web application template that you used to create this web app adds the following basic folder structure:

../_images/06-solution-explorer.png

Visual Studio creates some initial folders and files for your project. The primary files that you should be familiar with include the following:

File name Purpose
project.json The presence of a project.json file defines a .NET Execution Environment (DNX) project. It is the project.json file that contains all the information that DNX needs to run and package your project. For additional details, including the project.json file schema, see Working with DNX Projects.
global.json Visual Studio uses this file to configure the project.
appsettings.json This file allows you to include additional project information, such as connection string values. For more information, see Configuration.
Startup.cs The Startup class provides the entry point for an application. The Startup class must define a Configure method, and may optionally also define a ConfigureServices method, which will be called when the application is started. For more information, see Application Startup.
Index.cshtml This view contains the HTML for the default page of the view.
_Layout.cshtml This view contains common HTML for multiple pages of the web app.
HomeController.cs This controller contains the classes that handle incoming browser requests, retrieve model data, and then specify view templates that return a response to the browser.

Understanding MVC

This project uses ASP.NET MVC. MVC stands for model-view-controller. MVC is a pattern for developing applications that are well architected, testable, and easy to maintain. MVC-based applications contain:

  • Models: Classes that represent the data of the application and that use validation logic to enforce business rules for that data.
  • Views: Template files that your application uses to dynamically generate HTML responses.
  • Controllers: Classes that handle incoming browser requests, retrieve model data, and then specify view templates that return a response to the browser.

Understanding .NET Core

.NET Core 5 is a modular runtime and library implementation that includes a subset of the .NET Framework. .NET Core 5 has been designed for Windows, Linux and OS X. It consists of a set of libraries, called “CoreFX”, and a small, optimized runtime, called “CoreCLR”. .NET Core is open-source, so you can follow progress on the project and contribute to it on GitHub. For more information, see Choosing the Right .NET For You on the Server.

Entity Framework

Entity Framework (EF) is an object-relational mapping (ORM) framework. It lets you work with relational data as objects, eliminating most of the data-access code that you’d usually need to write. Using EF, you can issue queries using LINQ, then retrieve and manipulate data as strongly typed objects. LINQ provides patterns for querying and updating data. Using EF allows you to focus on creating the rest of your application, rather than focusing on the data access fundamentals.

Open the project.json file. In the dependencies section, you will see the following lines related to EF:

  "dependencies": {
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",

These lines show that you can issue EF commands from the command window and that the EF NuGet package is included with your project.

Create a data model and scaffolding

Entity Framework supports a development paradigm called Code First. Code First lets you define your data models using classes. A class is a construct that enables you to create your own custom types by grouping together variables of other types, methods and events. You can map classes to an existing database or use them to generate a database. In this tutorial, you’ll begin by creating the entity classes that define the data models for the Web application. Then you will create a context class that manages the entity classes and provides data access to the database. You will then configure EF and populate the database.

Create entity classes

The classes you create to define the schema of the data are called entity classes. If you’re new to database design, think of the entity classes as table definitions of a database. Each property in the class specifies a column in the table of the database. These classes provide a lightweight, object-relational interface between object-oriented code and the relational table structure of the database.

The Web app will have two new entities:

  • Book
  • Author

You will define a class for each in the Models folder within Solution Explorer. Each class will define the

Note

You can put model classes anywhere in your project. The Models folder is just a convention.

Right-click the Models folder and select Add > New Item. In the Add New Item dialog, select the Class template. In the Name edit box, type “Author.cs” and click OK.

../_images/15-add-new-item.png

Replace the default code with the following code:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ContosoBooks.Models
{
    public class Author
    {
        [ScaffoldColumn(false)]
        public int AuthorID { get; set; }
        [Required]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Display(Name = "First Name")]
        public string FirstMidName { get; set; }

        public virtual ICollection<Book> Books { get; set; }
    }
}

Repeat these steps to add another class named Book with the following code:

using System.ComponentModel.DataAnnotations;

namespace ContosoBooks.Models
{
    public class Book
    {
        [ScaffoldColumn(false)]
        public int BookID { get; set; }
        [Required]
        public string Title { get; set; }

        public int Year { get; set; }
        [Range(1, 500)]
        public decimal Price { get; set; }

        public string Genre { get; set; }

        [ScaffoldColumn(false)]
        public int AuthorID { get; set; }

        // Navigation property
        public virtual Author Author { get; set; }
    }
}

To keep the app simple, each book has a single author. The Author property provides a way to navigate the relationship from a book to an author. In EF, this type of property is called a navigation property. When EF creates the database schema, EF automatically infers that AuthorID should be a foreign key to the Authors table.

Add Scaffolding

Scaffolding saves you time and coding effort by automatically generating the starting point for your application’s CRUD (Create, Read, Update and Delete) operations. Starting from a simple model class, and, without writing a single line of code, you will create two controllers that will contain the CRUD operations related to books and authors, as well as the all the necessary views.

To add a scaffolding, right-click the Controllers folder in Solution Explorer. Select Add –> New Scaffolded Item.

../_images/15a-scaffold-menu.png

Note

If you don’t see the New Scaffolded Item option, make sure you have created the project using Individual User Accounts.

From the Add Scaffold dialog box, select MVC 6 Controller with views, using Entity Framework, then click the Add button.

../_images/15b-add-scaffold-db.png

Next, in the Add Controller dialog box, set the model class dropdown to Book (ContosoBooks.Models). Also, set the data context class to ApplicationDbContext (ContosoBooks.Models). Make sure the Generate views checkbox is checked. Then click the Add button.

../_images/15c-book-controller.png

As you can see in the above image, the Add Controller dialog box gives you the opportunity to select options for generating the controller and views.

This scaffold creates the code that provides a controller and a set of views. The views provide the UI and code to create, read, update, delete, and list data from the database.

Repeat the above scaffolding steps to create an Author controller and related views. Use the Author (ContosoBooks.Models) model class and the ApplicationDbContext (ContosoBooks.Models) data context class as shown in the following image.

../_images/15d-author-controller.png

In the Solution Explorer you’ll see that the new controllers were added within the Controller folder and new views were created within the Views folder.

../_images/15e-updated-solution-explorer.png

Configure the web app before including sample data

Next, you’ll add the Microsoft.Extensions.DependencyInjection package to your app. In Solution Explorer find and open project.json. In the dependencies section, begin by typing the following line at the end of the section.

../_images/15d2-di-intellisense.png

You will see that IntelliSense provides coding help as you type. Also, when you save project.json, Visual Studio will automaticaly resolve the new package reference.

../_images/15d3-package-restore.png

After the above line has been added, the dependencies section of your project.json file will appear as follows:

  "dependencies": {
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final",
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.FileProviderExtensions" : "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final",
    "Microsoft.Extensions.DependencyInjection": "1.0.0-rc1-final"
  },

Add sample data

Rather than entering several sample records by hand, you will add code that will by used to populate your database. Add a class named SampleData in the Models folder with the following code:

using Microsoft.Data.Entity;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace ContosoBooks.Models
{
    public static class SampleData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            var context = serviceProvider.GetService<ApplicationDbContext>();
            context.Database.Migrate();
            if (!context.Book.Any())
            {
                var austen = context.Author.Add(
                    new Author { LastName = "Austen", FirstMidName = "Jane" }).Entity;
                var dickens = context.Author.Add(
                    new Author { LastName = "Dickens", FirstMidName = "Charles" }).Entity;
                var cervantes = context.Author.Add(
                    new Author { LastName = "Cervantes", FirstMidName = "Miguel" }).Entity;

                context.Book.AddRange(
                    new Book()
                    {
                        Title = "Pride and Prejudice",
                        Year = 1813,
                        Author = austen,
                        Price = 9.99M,
                        Genre = "Comedy of manners"
                    },
                    new Book()
                    {
                        Title = "Northanger Abbey",
                        Year = 1817,
                        Author = austen,
                        Price = 12.95M,
                        Genre = "Gothic parody"
                    },
                    new Book()
                    {
                        Title = "David Copperfield",
                        Year = 1850,
                        Author = dickens,
                        Price = 15,
                        Genre = "Bildungsroman"
                    },
                    new Book()
                    {
                        Title = "Don Quixote",
                        Year = 1617,
                        Author = cervantes,
                        Price = 8.95M,
                        Genre = "Picaresque"
                    }
                );
                context.SaveChanges();
            }
        }
    }
}

You wouldn’t put this sample data class into production code, but it’s okay for this sample app scenario.

Next, in Solution Explorer, open the Startup.cs file. Add the following line of code at the end of the Configure method:

SampleData.Initialize(app.ApplicationServices);

After the above line has been added, the completed Startup.cs file will appear as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Data.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ContosoBooks.Models;
using ContosoBooks.Services;

namespace ContosoBooks
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            // Set up configuration sources.
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

            if (env.IsDevelopment())
            {
                // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
                builder.AddUserSecrets();
            }

            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddMvc();

            // Add application services.
            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");

                // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
                try
                {
                    using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                        .CreateScope())
                    {
                        serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                             .Database.Migrate();
                    }
                }
                catch { }
            }

            app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

            app.UseStaticFiles();

            app.UseIdentity();

            // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
            SampleData.Initialize(app.ApplicationServices);
        }

        // Entry point for the application.
        public static void Main(string[] args) => WebApplication.Run<Startup>(args);
    }
}

Notice in ConfigureServices the app calls Configuration.Get to get the database connection string. During development, this setting comes from the appsettings.json file. When you deploy the app to a production environment, you set the connection string in an environment variable on the host. If the Configuration API finds an environment variable with the same key, it returns the environment variable instead of the value that is in appsettings.json.

Build the web application

To make sure that all the classes and changes to your Web application work, you should build the application.

From the Build menu, select Build Solution.

The Output window is displayed, and if all went well, you see a succeeded message.

../_images/19-vs-build-output.png

If you run into an error, re-check the above steps. The information in the Output window will indicate which file has a problem and where in the file a change is required. This information will enable you to determine what part of the above steps need to be reviewed and fixed in your project.

Note

Before running the app, you must first create the database using the data migrations.

Using data migrations to create the database

Data migrations in EF are used to perform model updates throughout your entire application. By initially using data migrations to create your database, you can modify your database after the model has changed with simple steps. This will allow you to build and maintain your web app more efficiently. The alternative to data migrations, where model or schema changes are required after the database has been created, involves recreating your entire database.

Open a Command Prompt in the project directory (ContosoBooks/src/ContosoBooks).

Note

To open the Command Prompt, you can right-click the Windows start button and select Command Prompt from the menu.

To find the project directory, in Visual Studio you can right-click the project name (ContosoBooks) in the Solution Explorer and select Open Folder in File Explorer. Copy your project path from File Explorer so you can copy it to the Command Prompt. For example, enter the following from the Command Prompt to change directories:

cd C:\Projects\ContosoBooks\src\ContosoBooks

Note

Make sure that you have navigated to the ContosoBooks folder within the src folder.

Run each of the following commands from the Command Prompt:

dnu restore
dnx ef migrations add Initial
dnx ef database update

Note

If dnu restore is not a recognized command, you may have missed a prerequisite step (or part of a prerequisites step) at the beginning of this topic. However, first check if the Active version of the .NET Version Manager (dnvm) is checked. To do this, enter dnvm list in the command window. If there is no * next to any of the versions, set the active version by entering dnvm use 1.0.0-rc1-update1 -p, so that the appropriate version is selected.

The .NET Version Manager (dnvm) is a set of command line utilities that are used to update and configure .NET Runtime.

DNX stands for the .NET Execution Environment. The ef command is specificed in the project.json file of your project. For more information about dnvm, dnu, and dnx, see DNX Overview.

The “add Initial” command creates a migration named “Initial” that adds code to the project, allowing EF to update the database schema. The update command creates the actual database. After you run this command, the Migrations folder of your project will be updated as follows:

../_images/16-migrations.png

Note

For general EF command help, enter the following in the command window: dnx ef -?. For help with the add command, enter the following in the command window: dnx ef migrations add -?. And, for help with the update command, enter the following in the command window: dnx ef database update -?.

Also, you will be able to view the newly created database within SQL Server Object Explorer.

../_images/16a-database.png

Adding navigation

Update the navigation for the web app. From Solution Explorer, open the Views/Shared/_Layout.cshtml file. Find the following markup:

<li><a asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-controller="Home" asp-action="Contact">Contact</a></li>

Replace the above markup with the following markup:

<li><a asp-controller="Books" asp-action="Index">Books</a></li>
<li><a asp-controller="Authors" asp-action="Index">Authors</a></li>

The above changes will add a link to view Books and a link to view Authors. You created each of these views when you added scaffolding to the project.

Build the web application

To make sure that all the classes and changes to your Web app work, you should build the app again.

From the Build menu, select Build Solution.

Run the web app locally

Run the app now to see how you can view all of the products or just a set of products limited by category.

In the Solution Explorer, right-click the project name and select View -> View in Browser. As an alternative, you can press the F5 key.

The browser will open and show the web app. Click on the Books link at the top of the page.

../_images/19a-running-app.png

Close the browser and click the “Stop Debugging” icon in the toolbar of Visual Studio to stop the app.

Publish the web app to Azure App Service

In Solution Explorer of Visual Studio, right-click on the project and select Publish.

../_images/20-vs-publish.png

In the Publish Web window, click on Microsoft Azure Web Apps and log into your Azure subscription.

../_images/21-vs-publishwebdb.png

Make sure you are signed in to Azure with your Microsoft account, then click New to create a new Web app in Azure.

../_images/22-vs-selectexistingdb.png

Enter a unique site name, and select an app service plan, resource group, and region. Also, choose to create a database server, along with a database username and password. If you’ve created a database server in the past, use that. When you’re ready to continue, click Create.

../_images/23-vs-createwebappdb.png

On the Connection tab of the Publish Web window, click Publish.

../_images/24-vs-publishwebdb-target.png

You can view the publishing progress in eith the Output window or the Azure App Service Activity window within Visual Studio.

../_images/25-vs-webpubactivity.png

When publishing to Azure is complete, your web app will be displayed in a browser running on Azure.

../_images/26-browserazure.png

For additional publishing information, see Publishing and Deployment.