aspnetrun
Published in

aspnetrun

Build Web Application with ASP.NET Core, Entity Framework Core in a Real-Word Example

This article explains aspnetrun basic realworld repository of github. This series of articles continues as per difficulty levels. This article intended for the beginners of asp.net core. You can follow the other articles at the end of the page.

Introduction

In this article we will show how to build web application on ASP.NET Core Web application using Entity Framework and Razor Pages.

By the end of the article, we will have an web application which implemented mini e-commerce pages over Product,Category and Contact entities.

Take a look at the final application.

You’ll learn how to:

  • Create an ASP.NET Core Web Application Project
  • Work with a Database using Entity Framework Core
  • Bootstrap 4 Theme Implementation
  • ASP.NET Core Identity Scaffolding and Identity Configuration
  • Authorization for Pages
  • ASP.NET Core Razor Tools — View Components, partial Views, Tag Helpers, Model Bindings and Validations, Razor Sections etc..
  • At the end, you’ll have a working web application running on your local machine.

Source Code

Get the Source Code from AspnetRunBasic RealWorld Github — Clone or fork this repository, if you like don’t forget the star :) If you find or ask anything you can directly open issue on repository.

Prerequisites

  • Install the .NET Core 3.x or above SDK
  • Install Visual Studio 2019 v16.x or above
  • Microsoft Sql Server Express (its comes with Visual Studio)

Background

You can follow the previous article which base application of this implementation of this Basic repository in a real-world example.

Check for the previous article which explained base of this repository.

Based on that we were created a basic infrastructure of crud operations on asp.net core web application from previous post. Over this repository, we are going to create a basic real-world web application with using ASP.Net Core best practices.

Start the Web Application

We are going to build our application on top of the basic crud implementation of this repository. So lets download — clone or fork this repository and open the solution.

At this point, we have a CRUD implemented Pages project. Run the project (Crtl + F5) to see everything is OK.

Rename Your Application

At this point, you can rename your application name by changing Solution and Project Names.

Select Solution file, Right Click -> Rename -> Your New Project Name..

Select Project file, Right Click -> Rename -> Your New Project Name..

Project Structure

Examine the project files

Here’s an overview of the main project folders and files that you will work with in our operations.

Entities folder

This folder include model classes which we use all layers and manage this entities when Entity Framework Core persist on database and other database operations. We will use this folder for the new Entity definitions.

Data folder

This folder represent our Data Layer and includes Entity Framework Core implementation. Also include Seed class in order to load data when application start-up. We will add our Entities as a DBSet into DBContext object.

Migrations folder

This folder generated from Entity Framework Core in order to perform Migrations to the database. We will not modify this folder.

Repositories folder

This folder represent our Business Layer and includes Repository classes which wrappers of Entity Framework Core DbContext object. Since this is the one solution, we decided to named folder as Repository due to implement both wrapping EF.Core and implement business related logic's in one class.

Pages folder

This folder represent our Presentation Layer and includes Razor pages and supporting files. We will extend existing pages and add new Areas to implement e-commerce web application.

Starting Our Project

This project will be basic implementation of e-commerce web application. So we should define our basic use case analysis. In this post we will create Product — Category — Contact entities and create its relation. Our main use cases;

  • Listing Products and Categories
  • Login the system as a user
  • Authorize the Product page only see the logon users
  • Contact page which send Message to company, include post operations
  • Subscribe e-mail list

Set Entities

Go to Entities folder into your project. This will be the tables of your project. In this post, we will use the Code First Approach of the Entity Framework Core. That’s why we write the entity classes at first.

Add or Edit Product, Category and Contact class into Entities folder.

public class Product
{
public int Id { get; set; }
[Required, StringLength(80)]
public string Name { get; set; }
public string Summary { get; set; }
public string Description { get; set; }
public string ImageFile { get; set; }
public int UnitPrice { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
[Required, StringLength(80)]
public string Name { get; set; }
public string Description { get; set; }
public string ImageName { get; set; }
}
public class Contact
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Phone]
[Required]
public string Phone { get; set; }
[Required]
public string Email { get; set; }
[MinLength(10)]
[Required]
public string Message { get; set; }
}

In Contact entity, we used some Data Anotations (Required, Phone, MinLength) in order to validate form when submit the contract form.

Set Data Layer

In order to manage these entities, we should create a data structure. To work with a database, we will use this class with the Entity Framework Core. The Entity Framework Core is an object-relational mapping (ORM) framework that provide data access over the DbContext class. Entity classes are not dependent on Entity Framework Core.

Ensure that every Entity classes in this DataContext class as a DbSet generic.

public class AspnetRunContext : DbContext
{
public AspnetRunContext(DbContextOptions<AspnetRunContext> options): base(options)
{}
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Contact> Contacts { get; set; }
}

At this point, You can rename your Context Class here.

Click the AspnetRunContext class definition, Ctrl + R + R or Right Click-> Rename -> Your New Context Name..

Configure Entity Framework DbContext into Asp.Net Core

Entity Framework Core DB context object should registered in DI when starting the application. Ensure that DbContext object into ConfigureServices method is configured properly.

public void ConfigureServices(IserviceCollection services) 
{
#region Database Connection
//// use in-memory database
//services.AddDbContext<AspnetRunContext>(c => c.UseInMemoryDatabase(“AspnetRunConnection”));
// add real database ependency
services.AddDbContext<AspnetRunContext>(c => c.UseSqlServer(Configuration.GetConnectionString(“AspnetRunConnection”)));
#endregion
services.AddRazorPages();
}

Update Connection String

If you use the real database, its required to set-up connection string information. In Asp.Net Core this configuration stored appsettings.json file;

“ConnectionStrings”: {
“AspnetRunConnection”: “Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=AspnetRunBasic;”
}

At this point, You can rename your Database name.

In appsettings.json file change the Initial Catalog=AspnetRunBasic name.

Create Database using EF.Core Migrations

After definition of connection string, its ready to create database. In order to create database with Entity Framework Core, we should use EF.Core Migrations feature.

Before that you should delete Migration folder in your project. Because we should create new fresh initial migration class for our project.

Open Tools -> NuGet Package Manager > Package Manager Console(PMC) and run the following command in the package manager console:

add-migration Initial

This command generates code to create the initial database schema which is based on the model specified in the YourNewContext class. The Initial argument is the migration name and any name can be used. After running the command, Entity Framework Core will create Migrations folder in order to track changes on the DbContext entities.

To commit these changes into the database, run the following command in the package manager console:

update-database

This command runs the Up method in the Migrations/{time-stamp}_Initial.cs file, which creates the database.

Now, you can check the database created from Sql Server Object Explorer. Check the newly created database under the following path: Open View -> Sql Server Object Explorer.

You will see the your project tables under the your new database name.

Create Business Layer

For the Business Logic Layer we are using Repository folder in order to manage business operations with using data access layer objects.

The name of the Repository, would not be appreciate for Business Layer but we are building one solution that’s why we select this name, you can modify with name of Service,Application,Manager, Helper etc..

So lets edit a Repository folder and edit to IProductRepository class and create IContactRepository in order to manage Product and Contact pages.

public interface IProductRepository
{
Task<Ienumerable<Product>> GetProductListAsync();
Task<Product> GetProductByIdAsync(int id);
Task<Ienumerable<Product>> GetProductByNameAsync(string name);
Task<Ienumerable<Product>> GetProductByCategoryAsync(int categoryId);
Task<Ienumerable<Category>> GetCategories();
}
public interface IContactRepository
{
Task<Contact> SendMessage(Contact contact);
Task<Contact> Subscribe(string address);
}

Lets implement this interfaces with using Data layer objects.

public class ProductRepository : IproductRepository
{
protected readonly AspnetRunContext _dbContext;
public ProductRepository(AspnetRunContext dbContext)
{
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public async Task<Ienumerable<Product>> GetProductListAsync()
{
return await _dbContext.Products.ToListAsync();
}
public async Task<Product> GetProductByIdAsync(int id)
{
return await _dbContext.Products
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Id == id);
}
public async Task<Ienumerable<Product>> GetProductByNameAsync(string name)
{
return await _dbContext.Products.Include(p => p.Category).Where(p => string.IsNullOrEmpty(name) || p.Name.ToLower().Contains(name.ToLower())).OrderBy(p => p.Name).ToListAsync();
}
public async Task<Ienumerable<Product>> GetProductByCategoryAsync(int categoryId)
{
return await _dbContext.Products.Where(x => x.CategoryId == categoryId).ToListAsync();
}
public async Task<Product> AddAsync(Product product)
{
_dbContext.Products.Add(product);
await _dbContext.SaveChangesAsync();
return product;
}
public async Task UpdateAsync(Product product)
{
_dbContext.Entry(product).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
}
public async Task DeleteAsync(Product product)
{
_dbContext.Products.Remove(product);
await _dbContext.SaveChangesAsync();
}
public async Task<Ienumerable<Category>> GetCategories()
{
return await _dbContext.Categories.ToListAsync();
}
}

Basically, In ProductRepository class, we managed all business related actions with using AspnetRunDataContext object. You can put all business logics into this functions in order to manage one place.

And also here is ContactRepository implementation;

public class ContactRepository : IcontactRepository
{
protected readonly AspnetRunContext _dbContext;
public ContactRepository(AspnetRunContext dbContext)
{
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public async Task<Contact> SendMessage(Contact contact)
{
_dbContext.Contacts.Add(contact);
await _dbContext.SaveChangesAsync();
return contact;
}
public async Task<Contact> Subscribe(string address)
{
// implement your business logic
var newContact = new Contact();
newContact.Email = address;
newContact.Message = address;
newContact.Name = address;
return newContact;
}
}

Don’t forget to add below references into your repository classes;

using System.Linq;
using AspNetRunBasic.Data;
using AspNetRunBasic.Entities;
using Microsoft.EntityFrameworkCore;

Register Repository Classes into ASP.NET Dependency Injection Engine

You should register this classes into ASP.NET Built-in Dependency Injection engine.That means we should recognize these classes into asp.net core.

Open Startup.cs -> Go To Method ConfigureAspnetRunServices -> put your dependencies;

private void ConfigureAspnetRunServices(IserviceCollection services){
…..
#region project services
// add repository ependency
services.AddScoped<IproductRepository, ProductRepository>();
services.AddScoped<IcontactRepository, ContactRepository>();
#endregion
}

Create Presentation Layer

We were created a Default Web Application template for ASP.NET Core project. So that means we have a Razor Pages template into Pages folder.

ASP.NET Core Identity

According to requirements, the Login Page and Identity Management should be handled. For this kind of requirements, ASP.NET has scaffolding feature performs for the whole Identity operations.

Before we start in order to generate Login Pages, firstly we have to change Entity Framework Core DbContext object. You should change your Context inheritance to IdentityDbContext<IdentityUser> as below code.

It required below packages, add below nuget pages in our project.

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;

This is important because when Identity module generated, its looking for DbContext object which inherit from IdentityDbContext due to create identity tables for target DbContext object over this.

Scaffolding ASP.NET Core Identity

In order to create pre-built Login pages, follow the below steps;

Right Click Pages Folder -> Add -> New Scaffolding Item -> Identity -> Identity -> Click Add

Following screen, Select Login/Logout/Register -> Select Data context class -> Click Add

After applying these steps finally the Login pages generated from Visual Studio and should be added Areas folder as below image;

This is the ASP.NET Core Identity folder structure which include Login pages under the Areas->Identity->Pages->Account. It can be change but we leave as it is.

Starting with underscore (_) pages are special pages for asp.net core Razor template. We explain these pages later, you can see the Login / Logout / Register pages are ready for our project.

You can remove IdentityHostingStartup class, we don’t need to use for our project now.

One of the generated file is ScaffoldingReadme.txt. So this is instruction of how we activate Identity module, and you can this txt file. After following this text file Open Startup.cs — Configure() method. Method should be same as below respectively;

Now we can put the authorization our pages in order to force login to the user. Its very easy to set-up authorization into Razor pages. In example lets use the Products page.

Go To Product folder -> Open Index.cshtml.cs -> Add Authorize Attribute at the top of the class.

Its required this namespace -> using Microsoft.AspNetCore.Authorization;

Lets run the application and try to open Product Page;

This error says that you are configured ASP.NET Identity module has not default scheme. In order to provide default scheme we should configure Identity into Startup — ConfigureServices() method as below code.

Basically this code configure User entity, UI option and persistent database options. Also you can configure Password options over the IdentityOptions.

When we configure Identity with Entity Framework Core with this code; .AddEntityFrameworkStores<AspnetRunContext>();

That means we should also extend our database with Identity tables.

Update Database with Identity Tables

ASP.NET Identity module finished but not reflected to the database yet, so we should update database with ASP.NET Identity tables in order to use these tables through the application.

We followed the same steps when update the database; Run the following commands in the Package Manager Console:

Add-Migration IdentityAdded
Update-Database

You can see new Migration class added under the Migrations folder related with IdentityAdded operation. Also You can see from Sql Server Object Explorer that the Identity tables is added to the database;

Now, Run the application Click the Products link and see the result as below;

Anymore for Products page, without login users cannot be access.

Its not meaningfully when e-commerce application authorize Product page but we will use an example of authorization. You can change your authorized page as per your design.

Adapt UI Pages with Bootstrap 4

Since here we developed Product Data and Business Layer and also apply ASP.NET Identity module in our project. So in presentation layer we should apply some theme and layouts for listing this categories and its products on the page.

So the next steps should cover below parts;

  • Bootstrap 4 Theme Implementation
  • ASP.NET Core Razor Tools — View Components, partial Views, Tag Helpers, Model Bindings and Validations, Razor Sections etc..

For the rest of the application, I recommend to follow aspnetrun e-books in order to develop step by step a real-world application in every level of asp.net core.

Conclusion

This article demonstrate that how to build a basic e-commerce web application in a one solution and one project with ASP.NET Core & Entity Framework Core which used main components; razor pages, middlewares, dependency injection, configuration, logging. Provided that to create websites with minimum implementation of asp.net core based on HTML5, CSS, and JavaScript. We created a sample basic e-commerce product record management system and performed post operations on it.

For the rest of the application, I recommend to follow aspnetrun e-books in order to develop step by step a real-world application in every level of asp.net core.

Whats Next ?

You can follow this article series with implementation of layered architecture on aspnet core repository.

Continue with next article which explained layered architecture of aspnetcore repository.

What is AspnetRun ?

A starter kit for your next ASP.NET Core web application. Boilerplate for ASP.NET Core reference application with Entity Framework Core, demonstrating a layered application architecture with DDD best practices.

There are 6 asp.net core repositories from beginner to senior level in order to leverage your asp.net core skills and demonstrate real-world implementations.

Check all AspnetRun repositories on Github

Check AspnetRun web site to download e-book that explains step-by-step development of real-world examples.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mehmet Ozkaya

Mehmet Ozkaya

Software/Solutions Architect, Udemy Instructor, Working on Cloud-Native and Serverless Event-driven Microservices Architectures https://github.com/mehmetozkaya