How to Create WebAPI with ASP.NET Core 3.0 and Entity Framework Core

How to Create WebAPI with ASP.NET Core 3.0 and Entity Framework Core

In this guide, you'll learn how to WebAPI with ASP.NET Core 3.0 and Entity Framework Core and architect your ASP.NET Core applications to best take advantage of these capabilities.

Entity Framework is an object-relational mapper (ORM) tool. With time saving auto-generated code, support of LINQ and ease in unit testing makes it natural choice of .NET developers to work with databases. Entity Framework Core or EF Core is its newest version, “lightweight, extensible, open source and cross-platform”.

In this post, I’ll share my experience with *ebook is huge. To explain it better, I trimmed it down for a smaller application but kept the concepts intact.

I used this architecture in many projects. As application grows bigger and more developers join the team, then one really starts appreciating it’s separation into different projects, rules and patterns. This architecture implements Repository and Service *pattern, uses *[Dependency Injection](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/ "Dependency Injection*") and fulfils SOLID principles.

Introduction

In this article we’ll use EF Core to

  • Create a database for demo Library
  • Create a business logic and data access layer
  • Create and Inject service in *Library.WebApi *

Prerequisites

The Architecture

We’ll have two more projects (Class Library*) in our application dealing with database using *EF Core.

  • Library.Core
  • Library.Infrastructure

Library.Core

This project will hold the business logic, comprising

  • Entities
  • Interfaces
  • Services
  • Specification (Queries)

Library.Infrastructure

This is data layer. Everything to connect with database (DbContext*) to *repositories will be dealt here. It’ll have

  • LibraryDBContext
  • Repositories

Create and Seed Database

1 – Clone webAPI Application

2 – Add Core Project

Add new Class Library project with name Library.Core

3 – Entities

  • Add new folder named SharedKernal
  • In this folder add new abstract class BaseEntity
  • Add folder Entities *and add *Book, Category, Author
  • One to Many Relationships between entities

BaseEntity

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

namespace Library.Core.SharedKernal
{
    public abstract class BaseEntity
    {
        [Key, Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public DateTime CreatedDate { get; set; } = DateTime.UtcNow;
        public DateTime? ModifiedDate { get; set; } = null;
        public string CreatedBy { get; set; }
        public string ModifiedBy { get; set; } = null;
        public bool IsDeleted { get; set; } = false;
    }
}

All entities will inherit this base entity class

4 – Infrastructure Project

5 – Add Packages

6 – Create DBContext

  • Add new folder *Data *to create
  • Add new class LibraryDbContext *and inherit it from *DbContext
using Library.Core.Entities;
using Microsoft.EntityFrameworkCore;

namespace Library.Infrastructure.Data
{
    public class LibraryDbContext : DbContext
    {
        public DbSet<Author> Authors { get; set; }
        public DbSet<Book> Books { get; set; }
        public DbSet<Category> Categories { get; set; }
        public LibraryDbContext() { }

        public LibraryDbContext(DbContextOptions<LibraryDbContext> options) : base(options) { }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (optionsBuilder.IsConfigured == false)
            {
                var connectionString = "Server=(localdb)\\MSSQLLocalDB; Database=LibraryDb; Integrated Security=True;";

                optionsBuilder.UseSqlServer(connectionString);
            }
        }
    }
}

7 – Add Initial Migration

To make changes to our database schema whenever there’s change in our model (entities), we use Entity Framework Migrations feature.

  • In *Library.WebApi *project, add reference of *Library.Infrastructure *project
  • Open *Package Manager Console, *select *Library.Infrastructure *as *Default Project and *
PM> Add-Migration initial

  • We’ll get *Migrations *folder automatically and we’ll get a class created for us. We may edit it in accordance to our need.

  • Back in Package Manager Console use command to update database using this migration
PM> Update-Database

  • Open SQL Server Management Studio and let’s see database with name LibraryDb created

8 – Seed Data

As database is created, we got all the tables we were seeking to have in it. Let’s seed database with some demo data.

  • In Library.Infrastructure Project
  • Override OnModelCreating method in LibraryDBContext class
 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Author>().HasData(
                    new Author
                    {
                        Id = 1,
                        FirstName = "Elizabeth",
                        LastName = "Gilbert"
                    },
                    new Author
                    {
                        Id = 2,
                        FirstName = "Alex",
                        LastName = "Michaelides"
                    },
                      new Author
                      {
                          Id = 3,
                          FirstName = "Jayson",
                          LastName = "Greene"
                      },
                    new Author
                    {
                        Id = 4,
                        FirstName = "Jennifer",
                        LastName = "Weiner"
                    },
                     new Author
                     {
                         Id = 5,
                         FirstName = "Yangsze",
                         LastName = "Choo"
                     },
                     new Author
                     {
                         Id = 6,
                         FirstName = "Taylor",
                         LastName = "Jenkins Reid"
                     });

            modelBuilder.Entity<Category>().HasData(
                new Category { Id = 1, CategoryName = "Novel" },
                new Category { Id = 2, CategoryName = "Thriller" },
                new Category { Id = 3, CategoryName = "Memoir" }
                );

            modelBuilder.Entity<Book>().HasData(
                new Book { Id = 1, BookName = "City of Girls", AuthorId = 1, CategoryId = 1 },
                new Book { Id = 2, BookName = "The Silent Patient", AuthorId = 2, CategoryId = 2 },
                new Book { Id = 3, BookName = "Once More We Saw Stars", AuthorId = 3, CategoryId = 3 },
                new Book { Id = 4, BookName = "Mrs. Everything", AuthorId = 4, CategoryId = 1 },
                new Book { Id = 5, BookName = "The Night Tiger", AuthorId = 5, CategoryId = 1 },
                new Book { Id = 6, BookName = "Daisy Jones & The Six", AuthorId = 6, CategoryId = 1 }
            );
        }
  • New Migration is created
  • Update database again
PM> Add-Migration SeedData
PM> Update-Database

Repository

Database has seeded, now we’ll fetch this data in our webAPI and further make it available for UI application to display it. Repositories hold data access code. In this application we’ll see the magic of generic repositories, i-e repository that’ll take entity as a parameter and perform data access operations on it.

I know there’s in favour and against discussion in developers circles about repository pattern and sepcifically do we really need it in EF Core. I must admit, I’m in favour of this pattern. And in this example we’ll experience a working example on how repository and service pattern can result in

  • Less repetition of code
  • Centralised management data access code
  • Allow future facilitation of caching and unit testing

And how we can have different repositories and services for our Read and *Write *operations to achieve maximum performance, still requiring very less code change in case of change in database technology and architecture.

Service

Service layer consumes repository and exposes business logic.

Specifications

Best architectures adhere to SOLID Principles. Last thing any architect wants is need to change in classes (specifically core classes) whenever we want to query data with different predicate. That’s where this specification part of *Core *project comes to help.

using Library.Core.Entities;

namespace Library.Core.Specifications.Books
{
    public class BookWithAuthorAndCategorySpecification : BaseSpecification<Book>
    {
        public BookWithAuthorAndCategorySpecification() : base()
        {
            AddInclude(b => b.Author);
            AddInclude(b => b.Category);
        }
    }
}

Now when we can have multiple specifications *without making changes in our repository. Just against any entity we’ll have a new *specification class and call repository Get method with that class in the Service.

public async Task<IEnumerable<Book>> GetAllBooksAsync()
{
    var spec = new BookWithAuthorAndCategorySpecification();
    return await repository.ListAsync(spec);
}

Attach data layers to webAPI

  • Library.WebApi project
  • In ConfigureServices method of *Startup.cs *add following lines
            // Add DbContext 
            services.AddDbContext<LibraryDbContext>(cfg =>
            {
                cfg.UseSqlServer(
                    Configuration
                    .GetConnectionString("LibraryConnectionString"));
            });

            // Add Repository
            services.AddScoped<IGenericReadRepository, GenericReadRepository>();

            // Add Books Service
            services.AddScoped<IBookService, BookService>();

This will make BookService injectable in controller

Automapper

In *Library.WebApi *project add following package.

<PackageReference Include="AutoMapper" Version="9.0.0" />

Automapper is a widely used utility, which frees coders from mapping ViewModels to Models *in *controllers. This is a very useful tutorial in case you are new to that. Automapper also requires to be added in *ConfigureServices *method

 //Add AutoMapper
services.AddAutoMapper(typeof(Startup));

BooksController

Now BooksController code in webAPI will look like that

using AutoMapper;
using Library.Core.Interfaces;
using Library.WebApi.Resources;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Library.WebApi.Controllers
{
    [Authorize]
    public class BooksController : BaseApiController
    {
        private readonly ILogger<BooksController> logger;
        private readonly IMapper mapper;
        private readonly IBookService service;

        public BooksController(ILogger<BooksController> logger,
            IMapper mapper,
            IBookService service)
        {
            this.logger = logger;
            this.mapper = mapper;
            this.service = service;
        }

        [HttpGet]
        [ProducesResponseType(typeof(BookResultResource), 200)]
        public async Task<IActionResult> Get()
        {
            try
            {
                logger.LogInformation("In BooksController Get");

                var bookResource = new BookResultResource()
                {
                    UserFullName = GetUserInfo("name"),
                    UserName = GetUserInfo("preferred_username"),
                    Books =
                    mapper.Map<IEnumerable<BookResource>>(await service.GetAllBooksAsync())
                };

                return Ok(bookResource);
            }
            catch (Exception ex)
            {
                logger.LogError($"Error in BooksController: {ex.Message}");
                return BadRequest($"{BadRequest().StatusCode} : {ex.Message}");

            }
        }
    }
}

Library.Web.UI

We won’t need any change in this project, just build and run as usual like previous post. And this time by clicking “Fetch Books” *data will be served from database through *Library.WebApi BooksController.

Sample

Clone following repository for code sample

Please don’t forget to add Application IDs for your UI and WebApi projects in authprovider.js and appsettings.json respectively.

https://github.com/AhsanRazaUK/webapi-ef-core

Summary

So, what we learnt in this article

  • Create and seed database using Entity Framework Core Code-First
  • Create and use generic repository in service
  • Create queries (specifications)
  • Inject service to webAPI
  • Automapper

And as usual, feel free to contact me if this all went well for you? Happy coding!

How to make Web API with ASP.NET Core 3.0 and MongoDB

aspnet asp.net aspnetcore

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Hire ASP.Net Developers

Looking to outsource your asp dot net development requirement? ASP.Net is a special feature of the DOT Net framework created by Microsoft. At [HourlyDeveloper.io](https://hourlydeveloper.io/ "HourlyDeveloper.io"), we have a team of experienced...

Routing in MVC - ASP.NET Core Demystified

ASP.NET Core MVC has introduced quite a few concepts that new (or new-to-ASP.NET) web developers might have some difficulty getting caught up with. My ASP.NET Core Demystified series is designed to help these developers get started building their own custom, full-fledged, working AASP.NET Core applications. In

What is the ASP.Net Machine Account on my Computer?

Some users have reported the existence of the ASP.Net machine account. In this article, I will discuss what is asp.net machine account in windows 10/7 and how to disable it, asp.net machine account password, and can I delete asp.net machine account? .NET Framework is an application on Windows that requires the installation to run several apps or games. However, when the .NET Framework is downloaded and installed, the application automatically creates an ASP NET machine account.

ASP.NET Community Standup - ASP.NET Core Linker with David Fowler

David Fowler will be showing ASP.NET Core linker improvements on the way for .NET 5, and probably some other crazy experiments. Come join the fun! Community ...

Add asp.net Identity in empty project

LIKE | COMMENT | SHARE | SUBSCRIBE Today, in this tutorial you will see the process of adding an ASP.NET Identity to the ASP.NET Web Application developed in...