0% found this document useful (0 votes)
27 views

ASP.net Core 9 Web API CRUD With Entity Framework Core - Full Course With DDD, Clean Code & Best Practices

This document outlines a comprehensive course on building a .NET 9 Web API using Entity Framework Core, focusing on CRUD operations and best practices. It covers essential topics such as setting up the development environment, implementing Domain-Driven Design, and managing database interactions with PostgreSQL. The guide is suitable for developers of all experience levels and includes practical examples and source code available on GitHub.

Uploaded by

Kais Abid
Copyright
© © All Rights Reserved
Available Formats
Download as PDF or read online on Scribd
0% found this document useful (0 votes)
27 views

ASP.net Core 9 Web API CRUD With Entity Framework Core - Full Course With DDD, Clean Code & Best Practices

This document outlines a comprehensive course on building a .NET 9 Web API using Entity Framework Core, focusing on CRUD operations and best practices. It covers essential topics such as setting up the development environment, implementing Domain-Driven Design, and managing database interactions with PostgreSQL. The guide is suitable for developers of all experience levels and includes practical examples and source code available on GitHub.

Uploaded by

Kais Abid
Copyright
© © All Rights Reserved
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 34
0710272025 0:55 ASP.NET Gore # Web API CRUD with Ently Framework Cor - Full Course with DDD, Clean Code & Best Practices - codewit FREE NET Zero to Hero Advanced Course! Enroll Now 47 Aspnet Core Webapi Crud With Entity Framework Core Ful oO jewithmukesh ASPNET Core 9 Web API CRUD with Entity Framework Core - Full Course with DDD, Clean Code & Best Practices Mukesh Murugan, @iammukeshm The best way to truly master any technology is to build something with it—and nothing beats creating CRUD (Create, Read, Update, Delete) operations when it comes to learning the core concepts. These operations form the backbone of almost every application, making them the perfect starting point for hands-on learning, In this comnrehensive course. we'll walk vou throuah every sten of the nracess — from settina up yor @ Cookie Notice Co T Co pre This is by-far the most detailed guide available today for the NET Community and Developers. nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 138 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Ch 1 Code & Best Prats - code By the end of this article, you'll be able to easily build NET 9 Web APIs, follow best practices while dealing with Entity Framework Core, and stand out in your next backend development interview. Let's get started! PS, this guide will be valid for future releases of .NET too, like .NET 10 or above. FREE NET Zero to Hero Course! @ This article is part of my going post it in this series, subscribe to my YouTube Channel he end gar f this FREE course is to build scalable NET applica an Architecture! Lam building ¢ ach to the finale - P What We will Build? We will build a NET 9 Web API for managing movie details with comprehensive CRUD functionality, including: Create a New Movie: Add a new movie by providing details such as title, director, release date, and genre. Get a Movie by ID: Retrieve the details of a specific movie using its unique identifier. Get All Movies: List all movies. Update a Movie: Update the information of an existing movie by specifying its ID and the new details. Delete a Movie: Remove a movie from the database using its |D. Key Specifications: PostareSOL Database on Docker: Easilv set uo and manaae the database in a containerized @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 2134 0710272026 0055 ASP.NET Core © Web API CRUD wih Enty Framework Cote - Full Course with DDD, Clean Code & Best Practices - code Entity Framework Core: Leverage EF Core for seamless database interactions with code-first migrations. Entity Configurations: Maintain clean and scalable database mappings with dedicated configuration classes. Minimal APIs: Build lightweight and performant APIs with minimal boilerplate. Data Seeding & Migration Workflows: Simplify initial data population and schema management. In-Memory Database for Development (Optional): Speed up development with an in- memory database. Best Practices: Ensure clean, maintainable, and scalable code using industry-standard best practices. This Guide will be an invaluable resource for developers of all experience levels, providing hands- on experience with modern .NET development techniques and practical backend API implementation. Who is this Guide for? This guide is for NET developers of all experience levels looking to build scalable Web APIs with modern development practices. Full-stack and backend developers can gain practical insights into API development with PostgreSQL, Docker, and Minimal APIs. This is a very beginner friendly guide. Note that the entire source code of this implementation is available for FREE in my GitHub repository. You can find the links at the bottom of this article If you're eager to build a well-structured NET 9 Web API, this guide is for you. PreRequisites Here are the prerequisites, Visual Studio IDE - Install from here. @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redelt 84 (0710212025 00:55 ASP.NET Core 9 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit. s get started with the development. Open up Visual Studio IDE (I personally use Visual St Community Edition), and Project anew ASP.NET e WebA We will select the NET 9 Framework, and kee} erything else as the default, Make sure that you have enabled the Enable OpenAPI support checkbox Additional information ASP.NET Core Web API tinux See) Sey Se een Donets ee ea ae See Iwill cleanup the solution, and rem he weather forecast sample code that ships with the default NET template Ihave also Jasimple Get Endpoint to Program.cs that returns a ‘Hello rT ye hitps:Icodewithmakesh.combloglaspret-core-wabapi-crue-wi-enlty ramework-core-ullcoursa?ulm_sourcesreddit 4134 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt As we know that, starting from .NET 9 and above, the default NET Templates do not include Swagger. That's why we have OpenAPl as part of the project configuration. If you aren't already aware of this breaking change, | have written a article covering why Microsoft has taken this decision, and what are the alternatives to Swagger. You can read the article from below. Swagger is Dead? Here's the Alternative! Microsoft has introduced a new way to handle A mentation that makes tter. Want to know what's next, the alternatives, and how it will affect your work? Keep reading to find out However, let's install the Scalar Package and wire it up with our shiny new NET WebAPI Install-Package Scalar.AspNetCore Once installed, let’s integrate it with our Web API. Open up Program.cs and add in the following highlighted file if (app. Environment. IsDevelopment()) app.MapOpenapi(); app.MapScalarapireference(); Also, open the launchSettings,son file and add the below highlighted lines so that the ScalarU is launched as soon as the WebAPI runs. @ Cookie Notice nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 5194 (0710212025 00:55 ASP.NET Core 9 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit. ith th Jone, let's build and run our applic nN. This would open up the bro lar/vi as below Corn ep things simple for now, jowever, there are to} ns of cus! ‘omiz tions availab! NAPI and Scalar le know re about this, please ad this article wing a simple DDD, aka Domain Driven Design Approach to re our NET application. Domain-Driven Design (DDD) foc to match the busin >n modeling the s Jomain, ensuring a scalable and maintainable architecture. By following this approach, we aim to build a solution that is oth understandable and adaptable to char In @ LUIHUTT UESIyH patent, HE wase L hitps:Ieodewithmukesh.combloglaspret-core-wabapi-crue-wih-enlty ramework-core-ullcoursa?ulm_sourcesreddit 8138 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt properties and behaviors that all domain entities will share. This provides consistency and reduces code duplication across the project. Let's create a new folder named Models and add anew class named = EntityBase public abstract class EntityBase public Guid Id { get; private init; } = Guid.NewGuid(); Public DateTimeOffset Created { get; private set; } = DateTimeoffset.UtcNow; public DateTimeOffset LastModified { get; private set; } = DateTimeoffset.UtcNow; public void UpdateLastModified() { LastModified = DateTimeoffset .UtcNow; An EntityBase class serves as a foundational blueprint for all entities in a domain-driven application. It encapsulates common properties like Id , Created ,and LastModified , which are essential for tracking an entity's identity and lifecycle events. By centralizing these properties in a base class, we reduce code duplication and maintain a consistent structure across all entity classes. Making the class abstract ensures that it cannot be instantiated on its own, as it is meant to provide shared functionality rather than represent a standalone concept. Entities in the domain, suchas Movie , inherit from EntityBase to gain these common attributes and methods while defining their unique properties and behaviors. The use of access modifiers like private init forthe Id ensures immutability after creation, promoting integrity. Similarly, restricting setters for Created and LastModified enforces controlled updates, preserving reliable timestamp information. The UpdateLastModified method allows entities to track modifications seamlessly, supporting audit trails and data integrity Apt a a @ Cookie Notice Ne fol nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 7194 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit This entity will represent the core information about a movie in our system. An entity is typically defined by having an identity (Id) and encapsulating business rules that relate to its data. public sealed class Movie : EntityBase t nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit public string Title { get; private set; } public string Genre ( get; private set; } public DateTimeoffset ReleaseDate { get; private set; } public double Rating ( get; private set; } // Private constructor for ORM frameworks private Movie() Title = string-enpty; Genre = string. Empty; , private Movie(string title, string genre, DateTimedffset releasebate, double rating) { Title = title; Genre = genres ReleaseDate = releasebate; Rating = rating; public static Movie Create(string title, string genre, DateTimeOffset releaseDate, do ValidateInputs(title, genre, releaseDate, rating); return new Movie(title, genre, releaseDate, rating); public void Update(string title, string genre, DateTimeOffset releasebate, double rat { Validatetnputs(title, genre, releasebate, rating); Title = title; Genre = genre; ReleaseDate = releaseDate; @ Cookie Notice ase (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit if (string. IsNullorwhitespace(title)) throw new ArgumentException("Title cannot be null or empty.", nameof(title)); 4f (string. IsNullorwhiteSpace(genre)) throw new ArgumentException("Genre cannot be null or enpty.", nameof(genre)); if (releasebate > DateTimedffset.UtcNow) throw new ArgumentException("Release date cannot be in the future.", nameof(r if (rating < @ || rating > 1@) throw new ArgumentException("Rating must be between @ and 10.", nameof (rating The Movie class represents a movie entity in the application and builds on the EntityBase class. It includes properties like Title , Genre , ReleaseDate , and Rating to define the essential details of a movie. These properties have private setters to ensure that changes can only be made within the class, maintaining the integrity of the object. To create a new movie instance, the class provides a Create() method instead of directly exposing constructors. This approach allows input validation before the object is created, ensuring that the entity always starts in a valid state. The private constructor supports ORM frameworks that require parameter-less constructors to instantiate objects during database operations. The Update() method lets you modify the properties of a movie while ensui 1g the new values are valid. It updates the LastModified property to track when changes were made. Validation rules are enforced to prevent invalid data, such as empty titles or genres, future release dates, and ratings outside the 0-10 range. This design focuses on maintaining the correctness of the movie entity and enforcing domain rules at the entity level. It helps ensure that objects are always in a valid state and promotes clean and maintainable code. A @ Cookie Notice Wi int n the wuuer rarnaye manayer GuHaUre, nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redelt 9184 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit Install-Package Microsoft. EntityFrameworkCore Install-Package Microsoft. EntityFrameworkCore.Design Install-Package Npgsql.EntityFrameworkCore. PostgreSQL. These packages provide core EF functionality, design-time tools for migrations, and PostgreSQL database provider support, respectively. Adding DBContext Create a MovieDbContext class to manage the database operations for the application. | have created a folder named ‘Persistence’ and added a new class named Moviedbcontext_. Here's a clean and well-structured implementation: public class MoviebbContext (DbContextOptions options) : DbContext (options t public DbSet Movies => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.HasDefaultSchema("app"); mode1Builder .ApplyConfigurationsFromAssembly( typeof (MovieDbContext) Assembly) ; base. OnMiodelCreating(modelBuilder); > } The MoviebContext class is a custom implementation of EF Core’s DbContext _, which serves as the primary way to interact with the database. By inheriting from DbContext _, this class provides access to core database operations such as querying, updating, and saving changes. Th cor @ Cookie Notice 4 en: Thi collecuon maps aiecuy WW Ue | movies | LaVIE HT Ute Uatavase anu pruviues d Leal way tw nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 10198 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit perform CRUD operations using LINQ queries. Inthe onModelcreating method, the HasDefaultSchema call sets the schema to “app,” which is useful for organizing tables under a specific namespace in PostgreSQL. The call to ApplyConfigurationsfromAssenbly ensures that any entity configurations defined in the assembly are automatically applied, promoting cleaner and more maintainable code. Finally, the base.OnModelCreating(modelBuilder); call ensures that the default configurations defined by the bcontext are also applied. |EntityTypeConfiguration: Why? In Entity Framework Core, configuration for database entities can be done in multiple ways. One option is to use Data Annotations directly in the entity classes. However, this approach can clutter the model classes and tightly couple them to EF Core. A cleaner and more maintainable approach is to use the TEntityTypeconfiguration interface, which allows us to separate entity configurations into dedicated classes. This interface provides a configure method where you can define various database mapping details, such as table names, keys, relationships, constraints, and indexes. This decoupled approach improves code organization and promotes adherence to the Single Responsibility Principle, making your codebase easier to manage and extend. Additionally, it enables better reusability and flexibility, especially in larger projects where multiple entities require complex configurations. By using IentityTypecontiguration , you can centralize all database-specific logic for an entity, ensuring that your model classes remain focused solely on business logic. This separation also aligns well with migration and schema evolution scenarios, as all configurations are defined in one place, making it easier to maintain and update the database mappings over time. Under the Persistence folder, create a new folder called Configurations and add anew class MovieConfiguration @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 1138 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit // Set primary key builder.Haskey(m => m.Id); // Configure properties builder.Property(m => m.Title) -TsRequired() -HasMaxLength(288) ; builder.Property(m => m.Genre) TsRequired() -HasMaxLength(16@) ; builder.Property(m => m.ReleaseDate) TsRequired(); builder.Property(m => m.Rating) TsRequired(); // Configure Created and LastModified properties to be handled as inmutable and builder.Property(m => m.Created) -TsRequired() ValueGeneratedonadd() builder.Property(m => m.LastModified) IsRequired() ValueGeneratedonUpdate(); // Optional: Add indexes for better query performance builder .Hastndex(m => m.Title); The MovieContiguration class implements | IEntityTypeConfiguration allowing us to define how the Movie entity should be mapped to the database. This configuration is cleanly encapsulated in the | configure | method Ing p @ Cookie Notice t Co Ne 1d | property is treated as the primary key when the database schema is created. nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redelt 12184 0710272026 0055 ASP.NET Core © Web API CRUD wih Enty Framework Cote - Full Course with DDD, Clean Code & Best Practices - code Property configurations are specified using the Property method. For example, builder.Property(m => m.Title).TsRequired().HasMaxLength(2ee); ensures that the Title property is mandatory and has a maximum length of 200 characters. Similarly, other properties such as Genre , ReleaseDate ,and Rating | are also marked as required, with some constraints like maximum length. Timestamps are configured for the Created and LastModified properties. The line builder.Property(m => m.Created).TsRequired().ValueGeneratedonAdd(); ensures that Created is set when the entity is first added. On the other hand, builder.Property(m => m.LastModified) .IsRequired().ValueGeneratedonUpdate(); ensures that LastModified is updated whenever the entity is modified Finally, builder.HasIndex(m => m.Title); creates a database index on the Title column. This can significantly improve query performance when searching or filtering by Title This structured configuration keeps entity models clean and focuses purely on the domain logic, while all database-related settings are neatly managed in a separate class. Running PostgreSQL on Docker Container To quickly and efficiently set up a PostgreSQL instance, Docker is an ideal solution. It enables you to run a fully isolated database environment, without making changes to your local development setup. Before proceeding, ensure that Docker Desktop is installed on your machine. It's also beneficial to have a basic understanding of Docker. If you're new to Docker, feel free to check out my article to get up to speed. Create a new file named docker-conpose.yml at the root of the solution and add the following version: "3.8" @ Cookie Notice POSTGRES_USER: admin nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 13108 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit POSTGRES PASSWORD: secret POSTGRES_DB: dotnetHero ports ~ "5432:5432" volumes: - postgres_data:/var/ib/postgresql/data volumes: postgres_data This docker-conpose.yml _ file sets up a PostgreSQL service in a Docker container. It uses the official postgres image and assigns the container aname postgres. The service is configured to restart automatically if the container stops or the system reboots. The environment variables set up the default PostgreSQL user, password, and database (_ admin | secret ,and dotnetHero respectively). It also maps the PostgreSQL port 5432 on the container to the host's port 5432. , allowing external access to the database. Lastly, it uses a Docker volume ( postgres_data ) to persist database data even if the container is removed or restarted, ensuring data is not lost. I typically use pgAdmin to navigate through the objects in PostgreSQL databases. Once done, Open a terminal, navigate to the directory containing the docker-composeym|, and execute: docker-compose up -d This will pull the PostgreSQL image, set up the container, and expose it on port 5432 Running PostgreSQL in a Docker container is a great way to simplify your development and tes dif @ Cookie Notice ' ap, Otic Gpuwns. nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redelt 14198 0710272026 0055 ASP.NET Core © Web API CRUD wih Enty Framework Cote - Full Course with DDD, Clean Code & Best Practices - code 1. Using Local Installation: You can install PostgreSQL directly on your machine. While this, provides full control over the environment, it can be less portable and may lead to versioning issues when working across different systems. 2. Managed PostgreSQL Services (Cloud): Services like Amazon RDS, Azure Database for PostgreSQL, and Google Cloud SQL offer fully managed PostgreSQL instances. These are ideal for production environments where scalability, availability, and maintenance are crucial. 3. Virtual Machines: Running PostgreSQL in a virtual machine (VM) is another option, especially when you need a more isolated environment or specific configurations. However, this is heavier than using Docker and requires more system resources. Each option has its advantages depending on your project's needs, from ease of use with Docker to the scalability and maintenance benefits of managed cloud services. Connection String Configuration Next, let’s configure the connection string for your PostgreSQL database. Open the appsettings.json file and add the following: "Connectionstrings": { “DefaultConnection": "Host=localhost ;Port=5432;Database=dotnetHero;Username=admin;Passh The key “DefaultConnection" can be customized, but make sure to use the same name consistently in your code when registering the DbContext, as it will reference this key for database connection details. Ri To P @ Cookie Notice nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 15108 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit builder. Services .AddDbContext(options => { var connectionString = builder. configuration.GetConnectionString("DefaultConnection”) options UseNpgsql (connectionstring) ; 5 Explanation: AddDbContext : This registers the MovieDbcontext with the dependency injection container, enabling it to be used throughout the application. UseNpgsql: This method tells EF Core to use PostgreSQL. as the database provider, with the connection string fetched from _ appsettings. json GetConnectionString("DefaultConnection"): Retrieves the connection string with the key “DefaultConnection" from your appsettings.json file. With this configuration, the MovieDbcontext _ is now ready to interact with the PostgreSQL database using the specified connection string Adding the Code st Migrations Now, let's add the necessary migrations to generate the database schema based on your entity model, 1. Add a migration: Run the following command in the terminal to create a migration that will generate the database schema based on your MoviebbContext dotnet ef migrations add Initialcreate This will generate a migration named initialcreate |. You can replace this with any other deccrintive name if needed @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?utm_source=redlt 10108 (0710212025 00:55 ASP.NET Core 9 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit. with the Update the database: After adding the migration, you can apply it to the databa: following command ef database update This will execute the migration and create the database and tables (if they already ist) based on the defined | pbcontext and models. It applies the changes to the Po: SQL database sp fied in your connection string With this setup, you can now manage your database schema through EF Core migrations and easily sync changes with your PostgreSQL data And here is what my Migrations file looks like Now that we have aur database tables in place. we need same initial data to the Mavies table Hi hitps:ieodewithmakesh.combloglaspret-core-wabapi-crue-wih-enly sramework-core-ullcoursa?ulm_sourcesreddit 17134 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit In our MovieDbContext , add the following code. protected override void OnConfiguring(DbContextoptionsBuilder optionsBuilder) { optionsBuilder -UseAsyncSeeding(asyne (context, _, cancellationToken) => { var sampleMovie = await context Set ().FirstOrbefaultAsyne(b => b.T if (sampleMovie == null) { sampleNovie = Movie.Create("Sonic the Hedgehog 3", “Fantasy”, new Dat await context.Set() .AddAsync(sampleMovie) ; await context.SaveChangesAsync(); } » UseSeeding((context, _. var sampleMovie = context.Set().FirstOrDefault(b => b.Title == "Sc if (sampleMovie == null) { sampleNovie = Movie.Create("Sonic the Hedgehog 3", “Fantasy”, new Dat context .Set() .Add(sampleMovie) ; context .Savechanges(); } Y3 > EF 9introduced the UseSeeding and UseAsyncSeeding methods, which streamline the process of seeding the database with initial data. These methods simplify the way developers can implement custom initialization logic, offering a central location for all data seeding operations. The advantage of using these methods is that they integrate seamlessly with EF Core's migration locking mechanism, which ensures that data seeding happens safely and without concurrency issues = aa . oo tke E @ Cookie Notice s eve cor nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 10198 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt By leveraging UseSeeding and UseAsyncSeeding _, developers can manage and execute seeding tasks in a more organized, reliable, and concurrent-safe manner. In summary, this code checks if a movie with a specific title exists in the database. If it doesn't, it creates a new movie and saves it to the database. This is a common pattern used for seeding data or ensuring that certain records are present in the database. Finally, to trigger the seeding process, let's add a EnsureCreatedAsyne call, In Program.cs file, add the following, await using (var serviceScope = app.Services.CreateAsyneScope()) await using (var dbContext = serviceScope.ServiceProvider.GetRequiredService() . Then, it calls dbContext .Database.EnsureCreatedAsync() , which asynchronously checks if the database exists and creates it if it doesn’t. This ensures that the database is in place before any data operations are performed, preventing errors that might occur if the database is missing. This pattern is typically used in applications where database creation is required at startup but where migrations are not being used (e.g,, for small-scale or prototype applications) This ensures the database is created and the seed data is added. Important It's @ Cookie Notice Thi qu is nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 19108 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt created if it doesn't already exist, preventing errors when running the application for the first time. However, it bypasses the more robust and structured approach Recommended Approach for Production Use EF Core Migrations instead of | EnsurecreatedAsync . Migrations provide a systematic way to evolve your database schema while preserving existing data When to Use Ensurecreatedasync ? This pattern is ideal for: Development environments for quick testing Prototyping small-scale applications Adding the DTOs - ViewModels DTOs (Data Transfer Objects) play an essential role in software development by serving as lightweight objects used to transfer data between different parts of an application, such as between the backend and the frontend. They are particularly important in web APIs and service- oriented architectures. One primary reason for using DTOs is to decouple the internal domain models from the external representation sent over the network. Directly exposing domain entities can lead to security risks, data overexposure, and unwanted changes in the structure when evolving the application. DTOs allow developers to define exactly what data should be shared, providing better control over serialization and data formatting. Another advantage is improved performance and bandwidth efficiency. DTOs allow you to shape the response payload by sending only the required fields rather than the entire domain object. This reduces the size of the transmitted data, which is critical in scenarios involving slow networks or mobile applications. DTOs also play a vital role in data validation and mapping. They allow you to perform input we a . . Loe 7 fee @ Cookie Notice s ani In rep. - - . nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 20194 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit practice for designing scalable and maintainable APIs. In our case, if let's say a client requests for a Movie with ID #3, if the API returns the Movie class, it would lead to overexposure of fields like CreatedOn and other sensitive properties. So, instead of directly exposing the Movie entity, we can return a well-defined DTO that includes only the relevant and safe properties, suchas Title , Genre , ReleaseDate ,and Rating . By doing so, we maintain better control over the data sent to the client and ensure that sensitive fields like Createdon and LastModified are hidden from public access. Additionally, using DTOs provides flexibility in shaping the API responses. For example, we can create different DTOs based on the client requirements, such as a MovieDetailspTo with comprehensive information and a MovieSunmaryoT0 | with just the essential details for a list view. This approach also ensures that any future changes to the internal domain models do not directly impact the external API contract, making the system more maintainable and scalable. In cases where transformations are required, such as converting DateTimeoffset values toa user-friendly format, DTOs provide an ideal layer to handle such custom mappings without affecting the core domain logic. Overall, the use of DTOs fosters better API design, enhances security, and supports a cleaner separation of concerns. Let's create a new folder named pTos and add the following records. public record CreateMovieDto(string Title, string Genre, DateTimeOffset ReleaseDate, doub public record UpdateMovieDto(string Title, string Genre, DateTimeOffset ReleaseDate, doub public record MovieDto(Guid Id, string Title, string Genre, DateTimeOffset ReleaseDate, ¢ cre @ Cookie Notice me fol nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?utm_source=redlt 21104 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt The CreateMoviebto record encapsulates the data required when a client creates a new movie entry. This includes Title , Genre , ReleaseDate ,and Rating . By using this DTO, we ensure that the API only accepts the relevant information needed to initialize a movie. The UpdateMoviedto record handles the data when updating an existing movie. Its properties mirror those in CreateMoviedto _, as updating typically involves modi 1g the same fields as creation, Lastly, Movieoto is designed for responses sent back to the client. It includes an Id property to uniquely identify the movie along with the other fields. By returning this DTO instead ofthe full Movie | entity, we avoid exposing internal details and maintain control over the API's data contract. This setup using DTOs with records makes the API cleaner, more secure, and aligned with best practices for RESTful services. The IMovieService Interface Here is the core part of the implementation, services. Create a new folder named Services and add the following IMovieService _ interface. public interface IMovieService Task CreateNovieasync(CreateMoviebto conmand) ; Task GetMovieByIdAsync(Guid id); Task> GetAllMoviesAsync(); Task UpdateMovieasync(Guid id, UpdateMoviepto conmand) ; Task DeleteMoviessync(Guid id); The | CreatetiovieAsync method handles the creation of a new movie by accepting a Cpantalindantn | cammand and ratuenina the new crastad mavia a6. (inst antn Th @ Cookie Notice 6 G TEnumerable nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?utm_source=redlt 22184 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt Updatetoviersyne allows updating an existing movie. The method accepts the movie's identifier and an UpdateMoviedto _, which contains the updated data Lastly, DeleteMoviessync _ is responsible for deleting a movie based on its unique identifier. By defining these methods in the | INovieService | interface, the application maintains a clear separation of concerns, enabling easier testing, better maintainability, and adherence to SOLID principles, especially the Dependency Inversion Principle CRUD Operations - MovieService Implementation Now that we have defined the interface, Let's implement it. Create a new class named MovieService public class MovieService : IMovieService { private readonly MovieDbContext _dbContext; private readonly ILogger logger; public MovieService(MovieDbContext dbContext, TLogger logger) { _dbContext = dbContext; logger = logger; Let's add in the following CRUD Operations, one by one, Create @ Cookie Notice 5B. nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 224 ‘7102/2026 00:55 ASP.NET Core 9 Web API CRUD with Enty Framework Core - Full Gours wih DDD, Clean Code & Best Practices - codewit return new Moviebto( movie.Id, movie.Title, movie.Genre, movie. ReleaseDate, movie.Rating The CreateMovieasync method is responsible for handling the creation of a new movie in the database. It begins by invoking the | Movie.create | factory method, which encapsulates the entity creation logic. This ensures that any business rules or validations are enforced during the creation process. Anca tha mavia antity ie craatad it ie added tn the AhCantavt icing Addtcune Thic anaratinn marks the entity for tracking, signaling that it should be persisted to the database when changes are saved, Next, SaveChangesAsync _is called to persist the new movie entry to the database. Using asynchronous methods ensures that the API remains responsive and can handle other requests efficiently, Finally, the method returns a MovieDto object, which contains only the essential fields to be exposed to the client. This approach prevents overexposure of sensitive data and maintains a clean separation between the entity and the API's response model Read public async Task> GetAllMoviesAsync() return await _dbContext.Movies AsNoTracking() @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 24194 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit -ToListAsyne()5 The GetallMoviesAsync method retrieves all movies from the database without tracking changes for better performance. It maps each movie toa MovieDto_, ensuring only essential fields are returned. The use of | ToListAsyne allows for efficient asynchronous database access. public async Task GetMovieByIdAsync(Guid id) var movie = await _dbContext.Movies AsNoTracking() FirstorDefaultAsyne(m => m.Id id); if (movie == null) return null; return new MovieDto( movie.Id, novie.Title, movie.Genre, movie. ReleaseDate, movie. Rating Hy The GetNovieBytdasync method fetches a specific movie by its 1d from the database without tracking changes. If no matching movie is found, it returns _nul1_. If found, it maps the movie entity toa Movieoto and returns it, ensuring only essential data is exposed. Update @ Cookie Notice tin eens nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redeit 25104 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit } The UpdateMovieasyne method handles updating an existing movie in the database. It first searches for the movie by its Id. Ifno movie is found, it throws an ArgunentNullException If found, it updates the movie's properties using the provided UpdateMoviedto and then saves the changes to the database, This approach ensures efficient entity tracking and persistence within EF Core, Delete public async Task DeleteMovieasync(Guid id) var movieToDelete = await _dbContext.Movies.FindAsync(id) ; if (movieTobelete != null) { _dbContext .Novies Remove (movieTobelete) ; await _dbContext .SaveChangesAsync(); The eleteMoviersync method is pretty straightforward. It looks up the movie by its 1é_. If a match is found, it removes the movie from the database and commits the change by calling SavechangesAsyne()__. If no movie is found, it quietly does nothing—no exceptions, no drama Some of you might argue that throwing an exception when a movie isn’t found would be more explicit and help catch potential issues. However, in this case, it’s unnecessary overhead for a simple delete operation. If the movie doesn’t exist, there's nothing to remove, and the outcome is already what we want. Keeping the logic clean and lightweight makes the code easier to maintain and avoids unnecessary exception handling NM. @ Cookie Notice Ne fur a PlOviuc @ SHnPIC aU CONLIRE Way WU SEC UP ATID WHIHUUL WE UVEI ICOM UF Cur Ue: nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?utm_source=redlt 20104 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit These are the conventional routes following REST Standards. Conventional REST API Standards POST /api/movies : Add anew movie GET /api/movies : Get all movies GET /api/novies/{id} : Get a movie by ID PUT /api/movies/{id) : Update a movie's details DELETE /api/movies/{id) : Delete a movie by ID Here's how we can wire up the MovieService logic with the necessary API routes First, we register the IMovieService and its implementation in the Program.cs. This allows us to inject the service into our endpoints. builder. Services.AddTransient(); The above mentioned 5 CRUD Endpoints can be added into the Program.cs as well, but | would do something better. To make the code cleaner and more maintainable, we can organize the API routes into a separate class, which helps keep the Program.cs file more focused and less cluttered, This structure also improves readability and reusability I created a folder named Endpoints and added a class called ~MmovieEndpoints public static class MovieEndpoints { public static void MapMovieEndpoints(this IEndpointRouteBuilder routes) { @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?utm_source=redlt 27104 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit movieApi.mapGet("/", async (IMovieService service) < var movies = await service.GetAllMoviesAsync(); return TypedResults.Ok (movies) ; moviedpi .MapGet("/{id}", async (IMovieService service, Guid id) => var movie = await service.GetMovieByIdAsync(id) ; return movie is null ? (1Result)TypedResults .NotFound(new { Message = $"Movie with ID {id} not : TypedResults..Ok(movie) ; vs movieApi.MapPut("/{id}", async (IMovieService service, Guid id, UpdateMovieDto co { await service.UpdateMovieAsync(id, command) ; return TypedResults.NoContent(); ys movieApi.MapDelete("/{id}", async (IMovieService service, Guid id) => await service.DeleteMovieasync(id) ; return TypedResults.NoContent(); vs The MovieEndpoints class defines a set of API routes for movie-related operations using Minimal API style. The MapMovietndpoints method is an extension for TEndpointRouteBuilder and is responsible for configuring the various HTTP methods (POST, GET, PUT, DELETE) for the /api/movies route. The method begins by defining a route group | /api/movies and tagging it as “Movies” for @ Cookie Notice nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 20194 0710272026 0055 ASP.NET Core © Web API CRUD wih Enty Framework Cote - Full Course with DDD, Clean Code & Best Practices - code GET /api/movies/ : This route retrieves all movies from the database by calling the GetAlIMoviesAsyne method and returns the list of movies as a 200 OK response. GET /api/movies/{id): This route fetches a movie by its ID. If the movie is found, it returns the movie details; if not, it responds with a 4@4 Not Found message. PUT /api/movies/{id) : This route allows updating an existing movie's details. It calls the UpdateMovieasync method with the movie's ID and updated data from the UpdateMoviedto .Itreturns a 204 No Content status upon successful update. DELETE /api/movies/{id} : This route deletes a movie by its ID. It returns a 204 No Content The overall structure keeps the AP! organized and clean, enabling scalable and easy-to-manage routes for the movie-related CRUD operations. Finally, add the following extension to your Program.cs to register the above defined endpoints. app.MapMovieEndpoints(); This will wire up all the movie-related routes, and your application is now ready to handle movie- related requests through these clean and structured API endpoints. Testing the API with Scalar That's everything you need to do from the code aspect. You can find the entire source code of this implementation on my GitHub repository, the link to which is available at the bottom of this article, Let's test this NET 9 CRUD Application now. Build and run the application, and open up the Scalar Ul. Her @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redelt 20104 ade & Bost Practices - codewit. ad s ‘on as the API fullcourse?ulm_sour ASP.NET Core 9 Web API CRUD with Entty Framework Core - Full Course with DDD, Clean Code & Best Practices - codewit. ut the Get All endpoint te 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt That wraps up our implementation! But there are still a few things you can do to elevate this NET 9 Web API even further. Here are some next steps to enhance its functionality: Add Logging: Enhance the observability of your application by integrating structured logging using Serilog, Logging provides insights into what's happening in your API, making it easier to troubleshoot issues. If you're new to Serilog, check out my detailed guide on integrating it into ASP.NET Core here. Add Input Validation: Although we've validated our domain layer, it's a good practice to validate data at the DTO level as well. This ensures that only valid data reaches the business logic. You can easily achieve this with the FluentValidation library. If you're unfamiliar with it, I've written a comprehensive tutorial here. Introduce Paging, Sorting, and Filtering: For larger datasets, adding features like paging, sorting, and filtering will significantly improve the performance and usability of your API. This makes it easy to retrieve specific subsets of data, particularly for endpoints that return large lists. Dockerize the Application: Dockerizing your application makes it more portable and scalable. It simplifies deployments across different environments. If you're new to Docker, check out my Getting Started Guide for Docker to learn how to containerize your NET applications. Deploy to the Cloud: Finally, take your application to the cloud! Whether it’s AWS, Azure, or Google Cloud, deploying your API to the cloud enhances scalability, security, and manageability, Each cloud provider has its own deployment strategies, but they all offer a variety of services to support your application. By following these steps, you can transform your API into a production-ready, robust solution that scales efficiently while offering a seamless experience to users St @ Cookie Notice Uh a lot rs! nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 22184 107}027025 0055 __-ASPNET Core 8 Web API CRUD with Enty Framework Core Full Course wih DDD, Clean Code & Best Practeus- codewt If you found this article useful, I'd love to hear your feedback! Did you enjoy it? What other topics would you like me to cover next? Drop a comment or reach out, and let me know what you'd like to see in the future. And if you think others might benefit from this article, feel free to share it with your network Sharing is caring, and it helps the community grow! Thanks for reading, and stay tuned for more helpful content! Source Code @ Grab the source code of the entire implementation by clicking here. Do Follow me ‘on GitHub Support & Ifyou have enjoyed my content and code, do support me by buying a coup e new content. CI will enable me to dedicate more time to research and cre Share this Article Share this article with your network to help others! ony What's your Feedback? Do let me know your thoughts around this article. @ Cookie Notice nips:feadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-fu-course?ulm_source=redelt 33194 (0710212025 00:85 ASP.NET Core 8 Web API CRUD with Entty Framework Core - Full Course with DOD, Clean Code & Best Practices - codewit 0 reactions 0 comments FREE .NET Zero to Hero Course Join 5,000+ Engineers to Boost your .NET Skills. | have started a .NET Zero to Hero Co! hat covers thing from the basics to advanced topics to help you with your NET Journey! Learn what your tial employers are looking for! © Enroll Now codewithmukesh dl web development simp! Hy 6a @ Cookie Notice nips:fcadewithmukesh.comblog/aspret-core-webapi-crud-with-enily-tramework-core-ful-course?ulm_source=redit 34134

You might also like