Entity Framework Core (EF Core).

Entity Framework Core (EF Core) is a modern, lightweight, and extensible version of the Entity Framework, which is an Object-Relational Mapper (ORM) for .NET applications. It allows developers to work with databases using .NET objects, eliminating the need for most of the data-access code that developers usually need to write. Below, we will explore the key concepts of EF Core, including the Code-First approach, DbContext and DbSet, migrations, the repository pattern and unit of work, and LINQ queries with async operations.

What is Entity Framework Core?

Entity Framework Core (EF Core) is a modern, lightweight, open-source Object-Relational Mapper (ORM) for .NET. It allows developers to interact with databases using C# objects, eliminating the need to write most raw SQL queries.

🧠 Think of EF Core as a bridge between your C# code and the SQL database.

Key Features of EF Core

  • Cross-platform: Works on Windows, Linux, macOS
  • LINQ support: Query databases using C# syntax
  • Change tracking: Tracks changes in objects to update the DB
  • Migrations: Manage schema changes via code
  • Lazy/Eager/Explicit Loading: Controls how related data is loaded
  • Concurrency Handling: Manages data conflicts in multi-user apps

There are two types of Entity Framework Core approaches that we follow to interact with the database.
  • Database First Approach.
  • Code First Approach.

What is the Code-First Approach?

In the Code-First approach, you define your database schema using C# classes, and EF Core generates the database from this code. You don’t need an existing database instead you start with code, then create and update the database using migrations.

How Code-First Works:

Step 1: Create C# classes to represent tables (called entities).
Step 2: Create a DbContext class to manage the database connection and sets.
Step 3: Configure EF Core in Program.cs.
Step 4: Use Migrations to generate the schema and apply it to the database.

Step-by-Step Example of Code-First Approach.

Step 1. Install EF Core NuGet Packages.

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

Step 2. Define Your Entity (Model)
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class Product
{
    [Key]                                // Defines primary key
    public int Id { get; set; }

    [Required]                           // NOT NULL
    [MaxLength(100)]                     // Max length for Name
    public string Name { get; set; }

    [Column(TypeName = "decimal(10,2)")] // Define precision for Price
    [Range(0, 99999.99)]                 // Validation range
    public decimal Price { get; set; }

    [Required]
    [DefaultValue(true)]                 // Default value
    public bool IsAvailable { get; set; } = true;
}

In Entity Framework Core, you can define constraints using Data Annotations (attributes on properties).

Step 3: Create a DbContext.
public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

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

This is your custom database context class, and it's a key part of using Entity Framework Core (EF Core) with the Code-First approach.
EF Core uses this class to:
  • Configure the connection to the database
  • Map your C# models (like Product) to database tables
  • Track changes and execute queries
  • Save data to the database
DbContext is the core class in EF Core that manages all database operations (querying, saving, updating, etc.).

DbSet<Product> tells EF Core: “I want a table called Products in the database, and each row will be a Product object.”

Step 4: Register the DbContext in Program.cs.
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
And in appSettings.json
"ConnectionStrings": {
  "DefaultConnection": "Server=.;Database=EFCoreDemo;Trusted_Connection=True;"
}
Here we are defining a connection string that will help us connect to our database locally or remotely.

Step 5: Add and Apply Migrations.
dotnet ef migrations add InitialCreate
dotnet ef database update

EF Core will:
  • Create a Migrations folder
  • Generate SQL commands
  • Apply them to your database
Step 6. Use the DbContext to Perform CRUD
public class ProductService
{
    private readonly AppDbContext _context;
    
    public ProductService(AppDbContext context)
    {
        _context = context;
    }

    public async Task AddProduct()
    {
        var product = new Product { Name = "Laptop", Price = 1500 };
        _context.Products.Add(product);
        await _context.SaveChangesAsync();
    }
}

EF Core will keep your code and database in sync using migrations, making your development fast, clean, and flexible.

What is the Database-First Approach?

In the Database-First approach, you start with an existing database, and Entity Framework Core generates the C# classes (models and DbContext) based on that database schema.

When to Use It?

  • You already have a pre-existing database
  • You're working with legacy systems
  • You want your C# models to match a database that someone else designed

Step-by-Step Example of Database-First Approach:

Step 1: Install Required NuGet Packages.
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

Step 2: Run the Scaffold Command
Use the following CLI command to reverse engineer your DB:
dotnet ef dbcontext scaffold "Your_Connection_String" Microsoft.EntityFrameworkCore.SqlServer -o Models

Explanation:
  • "Your_Connection_String" – The connection string to your existing DB
  • Microsoft.EntityFrameworkCore.SqlServer – The database provider
  • -o Models – Output directory for generated models and DbContext
What It Generates:
  • DbContext file → manages the connection to the DB
  • Model classes for each table → mapped to DB tables

What is the Repository Pattern?

The Repository Pattern acts as a mediator between the business logic and the data access layer. It hides the details of data access and provides a simple and consistent API for performing database operations.

Benefits:
  • Encapsulates data access logic
  • Promotes loose coupling
  • Makes unit testing easier
  • Clean separation of concerns

Dependancy Injection and Its Lifetime in ASP.NET Core.

Dependency Injection (DI) is a fundamental concept in ASP.NET Core. It allows you to write loosely coupled, testable, and maintainable code by injecting the required dependencies into your classes instead of hard-coding them. ASP.NET Core has a built-in DI container that supports constructor injection and handles object lifetimes efficiently.

What is Dependency Injection?

Dependency Injection (DI) is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. Rather than a class creating its own dependencies, they are provided from outside, typically via the constructor.

📌 In simple terms: A class doesn’t create what it needs — it receives it from someone else.

Use of Dependency Injection:

  • Promotes loose coupling
  • Makes code testable
  • Supports the separation of concerns
  • Encourages interface-based programming

Step-by-Step Implementation of Dependency Injection:

Step 1: Create a New ASP.NET Core Project: You can create a new project using the .NET CLI or Visual Studio.

dotnet new webapi -n MyApi
cd MyApi

Step 2: Define a Service Interface: Create an interface that defines the contract for the service.
public interface IProductService
{
   IEnumerable<string> GetProducts();
}
   

Step 3: Implement the Service: Create a class that implements the service interface.
   public class ProductService : IProductService
   {
       public IEnumerable<string> GetProducts()
       {
           return new List<string> { "Product1", "Product2", "Product3" };
       }
   }
   

Step 4: Registering Services in the Dependency Injection Container.
   var builder = WebApplication.CreateBuilder(args);

   // Register the ProductService with the DI container
   builder.Services.AddScoped<IProductService, ProductService>();

   var app = builder.Build();
   

Step 5: Injecting Dependencies into Controllers
   using Microsoft.AspNetCore.Mvc;

   [ApiController]
   [Route("api/[controller]")]
   public class ProductsController : ControllerBase
   {
       private readonly IProductService _productService;

       // Constructor injection
       public ProductsController(IProductService productService)
       {
           _productService = productService;
       }

       [HttpGet]
       public IActionResult Get()
       {
           var products = _productService.GetProducts();
           return Ok(products);
       }
   }
   

Step 6: Run the Solution.

Service Lifetimes in ASP.NET Core.

In ASP.NET Core, when you register a service in the Dependency Injection (DI) container, you must specify its lifetime. This tells the framework how long to keep the object in memory and how often to create a new one.

ASP.NET Core provides three service lifetimes:
  • Singleton
  • Scoped
  • Transient
Singleton: A single instance is created once and shared throughout the application's entire lifetime.
Use When:
  • The service is stateless and thread-safe
  • You want to cache or reuse resources
  • Examples: Logging, Configuration, In-memory cache

Scoped: A new instance is created per HTTP request. The same instance is reused within that request.
Use When:
  • You want to maintain state only during a single request
  • You’re working with Entity Framework Core DbContext

Transient: A new instance is created every time the service is requested (even multiple times within the same request).
Use When:
  • Service is lightweight and stateless
  • You need fresh data or processing logic every time
Example:
builder.Services.AddSingleton<ISingletonService, MyService>();
builder.Services.AddScoped<IScopedService, MyService>();
builder.Services.AddTransient<ITransientService, MyService>();

Example: Unit Testing with DI.
var mockService = new Mock<IProductService>();
mockService.Setup(x => x.GetAll()).Returns(new[] { "Test Product" });

var controller = new ProductsController(mockService.Object);

var result = controller.GetAll();

Thanks to DI and interface-based design, testing is simple and clean.

Dependency Injection in ASP.NET Core is not just a feature — it’s a core part of the framework. By registering services properly, choosing the right lifetimes, and following interface-based design, you can build robust, maintainable, and testable web applications with ease.

Model Binding and Model Validation in ASP.NET Core

In ASP.NET Core Web API or MVC, Model Binding and Model Validation work together to handle incoming HTTP requests cleanly and securely.

What is Model Binding?

Model Binding is the process by which ASP.NET Core automatically maps incoming HTTP request data (from the query string, form data, route, headers, or body) to C# parameters or objects.

Sources of Model Binding:

Source Attribute Used (Optional) Example
Query string [FromQuery] /api/products?name=TV
Route [FromRoute] /api/products/5
Body (JSON) [FromBody] POST with JSON payload
Form data [FromForm] Used in HTML form uploads
Header [FromHeader] Custom header values

Here's a comprehensive example demonstrating all types of Model Binding in ASP.NET Core Web API — using [FromRoute], [FromQuery], [FromBody], [FromHeader], and [FromForm].

ASP.NET Core Model Binding Example:

Step 1: Model Class:
public class ProductDto
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Step 2: Controller with All Model Binding Types
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    // 1. FromRoute Example
    // URL: /api/products/5
    [HttpGet("{id}")]
    public IActionResult GetById([FromRoute] int id)
    {
        return Ok($"FromRoute: Product ID = {id}");
    }

    // 2. FromQuery Example
    // URL: /api/products/filter?name=Laptop&price=1000
    [HttpGet("filter")]
    public IActionResult Filter([FromQuery] string name, [FromQuery] decimal price)
    {
        return Ok($"FromQuery: Name = {name}, Price = {price}");
    }

    // 3. FromBody Example
    // POST JSON: { "name": "Tablet", "price": 500 }
    [HttpPost]
    public IActionResult Create([FromBody] ProductDto product)
    {
        return Ok($"FromBody: Name = {product.Name}, Price = {product.Price}");
    }

    // 4. FromHeader Example
    // Headers: X-User-Id: 101
    [HttpGet("secure")]
    public IActionResult Secure([FromHeader(Name = "X-User-Id")] int userId)
    {
        return Ok($"FromHeader: User ID = {userId}");
    }

    // 5. FromForm Example
    // Form Data: name=Phone, price=300
    [HttpPost("upload")]
    public IActionResult Upload([FromForm] ProductDto product)
    {
        return Ok($"FromForm: Name = {product.Name}, Price = {product.Price}");
    }
}

What is Model Validation?

Model Validation ensures that the data received from the client meets the specified rules and constraints. It runs after model binding and before executing the controller action.

Common Validation Attributes:
  • [Required]: Field must not be null/empty
  • [StringLength]: Limits string length
  • [Range]: Specifies a numeric range
  • [EmailAddress]: Validates email format
  • [RegularExpression]: Pattern-based validation
Example of Model Validation:
public class Product
{
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    [Range(1, 10000)]
    public decimal Price { get; set; }
}

[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState); // Returns validation errors
    }

    return Ok(product);
}

Flow: Model Binding + Validation

Client Request (JSON or Query) 
     
Model Binding (Maps request to C# model)
     
Model Validation (Validates using attributes)
     
Action Method Executes (if valid)

Purpose of Program.cs File in ASP.NET Core Application.

In an ASP.NET Core application, the Program.cs file is the entry point where everything begins. Whether you’re building a Web API, MVC app, or minimal API, this file is responsible for bootstrapping the application and configuring services, defining middleware, and launching the server.

Understanding the role and flow of Program.cs is essential for every ASP.NET Core developer.

What is Program.cs?

In ASP.NET Core, Program.cs contains the main method that runs when the application starts. With the newer .NET 6 and later versions (using the minimal hosting model), Program.cs is simplified and more readable.

📌 In short: Program.cs sets up everything your app needs before it starts handling requests.

Key Responsibilities of the Program.cs

  • Application Entry Point: The Program.cs file contains the Main method, which is the starting point of the application. When the application is run, this method is executed first.
  • Host Configuration: It sets up the web host, which is responsible for handling HTTP requests and managing the application's lifecycle.
  • Service Registration: It configures services that the application will use, such as dependency injection, middleware, and other services.
  • Middleware Pipeline: It defines the middleware pipeline, which processes incoming requests and outgoing responses.
  • Environment Configuration: It allows for configuration based on the environment (Development, Staging, Production).


ASP.NET Core Program.cs File:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddControllersWithViews(); // For MVC
builder.Services.AddEndpointsApiExplorer(); // For API documentation
builder.Services.AddSwaggerGen(); // For Swagger UI

var app = builder.Build();

// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage(); // Show detailed error pages in development
}
else
{
    app.UseExceptionHandler("/Home/Error"); // Redirect to error page in production
    app.UseHsts(); // Use HTTP Strict Transport Security
}

app.UseHttpsRedirection(); // Redirect HTTP requests to HTTPS
app.UseStaticFiles(); // Serve static files (CSS, JS, images, etc.)

app.UseRouting(); // Enable routing

app.UseAuthorization(); // Enable authorization middleware

// Configure endpoints
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}"); // Default route

app.Run(); // Start the application

ASP.NET Core Program Flow

Step What Happens? Analogy
CreateBuilder Build the kitchen & staff Set up the services needed
AddServices Add chefs, waiters, and recipes Register controllers, DB, and auth
Build() Open the restaurant Create the app instance
UseMiddleware() Define the rules of service Add routing, HTTPS, and error handling
MapEndpoints() Open the door for customers Route incoming requests
Run() Start serving customers Start the web server

Interview Question Related to Program.cs File.

1. What does Program.cs do?

Program.cs is the entry point of an ASP.NET Core application. It configures everything needed before the application starts handling requests.

Responsibilities of Program.cs:
  • Build and configure the application host
  • Register services (like controllers, DbContext, etc.) into the Dependency Injection (DI) container
  • Configure the middleware pipeline to handle requests and responses
  • Set up routing, authentication, CORS, Swagger, etc.
  • Run the application
Example:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // Add services

var app = builder.Build();
app.UseRouting();                  // Middleware
app.MapControllers();              // Endpoint mapping
app.Run();                         // Start server

2. In what order does middleware execute?

Middleware in ASP.NET Core executes in the order they are added in Program.cs.

Execution Flow:
  • Request comes in → first middleware executes
  • Each middleware does some work and optionally passes the request to the next
  • Last middleware returns a response → back through the pipeline in reverse
🧠 Key Rule:
Order matters – if UseRouting() comes after UseEndpoints(), routing won’t work!

3. How do you add a service or middleware?

Add a Service: Use builder.Services to register a service with the Dependency Injection container:
builder.Services.AddControllers();          // Built-in
builder.Services.AddScoped<IProductService, ProductService>(); // Custom service

Add Middleware: Use app.UseXyz() to insert middleware in the pipeline:
app.UseRouting();
app.UseAuthorization();

4. Where do you configure routing?

Routing is configured in Program.cs using UseRouting() and MapControllers() or MapControllerRoute().
Attribute Routing:

Enable with MapControllers():
app.UseRouting();
app.MapControllers(); // Used with [Route] attributes in controllers

Convention-Based Routing:
Enable with MapControllerRoute():
app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

The Program.cs file is the heart of your ASP.NET Core application. It controls everything — from startup to shutdown. By learning its flow and responsibilities, you can debug better, structure your app well, and ace backend interviews.

Routing in ASP.NET Core.

Routing is a fundamental concept in ASP.NET Core that enables the framework to map incoming HTTP requests to specific endpoints in your application. It plays a crucial role in defining how URLs are structured and how they correspond to the actions in your application. This article will provide a detailed overview of routing in ASP.NET Core, including its types, configuration, and examples.

What is Routing?

Routing is the process of directing an incoming HTTP request to the appropriate handler based on the URL and HTTP method. In ASP.NET Core, routing is handled by the middleware, which inspects the request and matches it against defined routes.

Which Middleware Handles Routing?

In ASP.NET Core, routing is handled by two key middleware components:

1. UseRouting() Middleware

  • Purpose: Matches the incoming HTTP request to the route template (defined via MapControllerRoute, attribute routing, etc.).
  • Placement: Must come before UseAuthorization() and UseEndpoints()

2. UseEndpoints() Middleware
  • Purpose: Executes the matched route handler (e.g., controller action, Razor page, minimal API).
  • It finalizes the routing decision made by UseRouting().

Types of Routing

ASP.NET Core supports two main types of routing:

  • Convention-based Routing: This is the default routing mechanism that uses predefined patterns to match incoming requests. It is typically used in MVC applications.
  • Attribute Routing: This allows developers to define routes directly on the controller actions using attributes. This method provides more control and flexibility over the routing configuration.

Key Note:
  • MapControllers(): Enables attribute routing ([Route("api/[controller]")])
  • MapControllerRoute(): Enables convention-based routing (like {controller}/{action}/{id?})

Convention-Based Routing in ASP.NET Core

Convention-based routing follows a predefined pattern to map incoming URLs to controller actions. This routing logic is configured centrally, usually in the Program.cs or Startup.cs file.

It's called “convention-based” because your app follows naming conventions for controllers, actions, and parameters to match the routes.

How to configure (Program.cs):
var builder = WebApplication.CreateBuilder(args);

// Add services to the container
builder.Services.AddControllersWithViews(); // For MVC
builder.Services.AddControllers(); // For Web API

var app = builder.Build();

// Configure the HTTP request pipeline
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

// Configure endpoints
app.UseEndpoints(endpoints =>
{
    // MVC Routing
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    // API Routing (attribute routing will be used)
    endpoints.MapControllers();
});

app.Run();
  • controller=Home: default controller
  • action=Index: default action
  • id?: optional parameter

Example:
public class ProductsController : Controller
{
    public IActionResult Details(int id)
    {
        return View(); // Returns View for /products/details/5
    }
}

Request:
GET /products/details/5

Matched By Pattern:
{controller=Products}/{action=Details}/{id=5}

Benefits of Convention-Based Routing:
  • Centralized route definitions
  • Easier to manage in large MVC apps
  • Reduces redundancy

Limitations:
  • Less flexible for APIs
  • It can become confusing with too many controllers/actions

Attribute Routing in ASP.NET Core

Attribute routing uses attributes directly on controller classes and action methods to define the routing rules. This provides more control and makes the routing explicit and readable.

Introduced in ASP.NET Web API and now standard in ASP.NET Core.

How To Use:
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAll()
    {
        return Ok("All Products");
    }

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        return Ok($"Product {id}");
    }

    [HttpPost]
    public IActionResult Create(Product product)
    {
        return Ok("Product Created");
    }
}

Request:

URL Method Action Called
GET /api/products [HttpGet] GetAll()
GET /api/products/2 [HttpGet("{id}")] GetById(2)
POST /api/products [HttpPost] Create()

Benefits of Attribute Routing:
  • Better suited for RESTful APIs
  • Greater clarity and control per action
  • Easy to document and maintain

How To Pass Multiple Values in a Request?

There are multiple ways to pass more than one parameter in a Request. Let's discuss each of them one by one:

1. Pass via Query String.
Query parameters are used to send data to the server in a key-value format. For example, in the URL:
https://localhost:5001/api/products?category=electronics&sort=price
The query parameters are category and sort, with values electronics and price, respectively.

You can access query parameters in your controller actions without needing to define them in the route. Here’s how you can do it:

Example of Using Query Parameters:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    private static readonly List<Product> _products = new()
    {
        new Product(1, "Laptop", 999.99m, "electronics"),
        new Product(2, "Mouse", 25.50m, "accessories"),
        new Product(3, "Smartphone", 699.99m, "electronics")
    };

    [HttpGet]
    public IActionResult Get([FromQuery] string category, [FromQuery] string sort)
    {
        var products = _products.AsQueryable();

        if (!string.IsNullOrEmpty(category))
        {
            products = products.Where(p => p.Category == category);
        }

        if (sort == "price")
        {
            products = products.OrderBy(p => p.Price);
        }

        return Ok(products.ToList());
    }
}

2. Pass Multiple values via Route Parameters.
In ASP.NET Core, you can pass multiple values via route parameters by defining them in the route template. This allows you to capture multiple segments of the URL as parameters in your controller action. Here’s how to do it:

To get a product by category and ID:
GET https://localhost:5001/api/products/electronics/1

Example of Using Query Parameter:
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    // Sample data
    private static readonly List<Product> _products = new()
    {
        new Product(1, "Laptop", "electronics"),
        new Product(2, "Mouse", "accessories"),
        new Product(3, "Smartphone", "electronics")
    };

    // Action method to get product by category and ID
    [HttpGet("{category}/{productId}")]
    public IActionResult GetProduct(string category, int productId)
    {
        var product = _products.FirstOrDefault(p => p.Id == productId && p.Category == category);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }
}

public record Product(int Id, string Name, string Category);

Bonus: For PUT/POST requests, we usually send JSON data in the body.
{
  "name": "Laptop",
  "price": 1500,
  "category": "Electronics"
}

Example Controller Action Method:
[HttpPost]
public IActionResult AddProduct([FromBody] Product product)
{
    // Access product.Name, product.Price, etc.
    return Ok($"Added: {product.Name}");
}

Note: You can only bind one complex object from the body using [FromBody]. If you need to pass multiple complex objects, wrap them into a single class.

Conclusion.

Understanding how routing works in ASP.NET Core Web API, especially the use of HTTP methods like GET, POST, and the power of attribute routing is essential for building clean, scalable, and RESTful services. By mapping specific URLs to controller actions using clear route definitions, you ensure that your API is both intuitive and maintainable

Understanding RESTful Principles in Web APIs.

In modern web development, RESTful APIs have become the standard for building scalable, stateless, and interoperable web services. At the heart of REST architecture are a set of HTTP methods — namely GET, POST, PUT, and DELETE — which define how clients interact with server resources.

In this article, you'll learn what each of these methods means, how they work, and when to use them with real-world examples using ASP.NET Core Web API.

What is REST?

REST (Representational State Transfer) is an architectural style for designing networked applications. It uses standard HTTP methods to perform CRUD operations (Create, Read, Update, Delete) on resources, which are usually represented as URLs.

A RESTful API is:
  • Stateless: Each request contains all the information needed.
  • Resource-based: Every piece of data is treated as a resource.
  • Uses standard HTTP verbs: GET, POST, PUT, DELETE, etc.

Core RESTful HTTP Methods

Let's break down the four primary HTTP methods used in RESTful APIs:

1. GET — Read Data

Purpose: Retrieve data from the server (read-only)
Safe and idempotent: Does not change server state
Status Code: 200 OK, 404 Not Found if the resource is missing

Example:
Request:
GET /api/products/1

Response:
{
  "id": 1,
  "name": "Laptop",
  "price": 1200
}

GET Request In ASP.NET Core:
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
    var product = _repo.GetById(id);
    if (product == null) return NotFound();
    return Ok(product);
}

2. POST — Create New Resource

Purpose: Send data to the server to create a new resource
Not idempotent: Calling multiple times will create multiple resources
Status Code: 201 Created

Example:
Request:
POST /api/products
Content-Type: application/json

{
  "name": "Tablet",
  "price": 500
}

Response:
201 Created
Location: /api/products/3

POST Request in ASP.NET Core:
[HttpPost]
public IActionResult CreateProduct(Product newProduct)
{
    _repo.Add(newProduct);
    return CreatedAtAction(nameof(GetProduct), new { id = newProduct.Id }, newProduct);
}

3. PUT — Update Existing Resource

Purpose: Update an existing resource entirely
Idempotent: The Same request can be repeated with the same result
Status Code: 200 OK, 204 No Content if no body returned

Example:
Request:
PUT /api/products/1
Content-Type: application/json

{
  "id": 1,
  "name": "Updated Laptop",
  "price": 1300
}

Response:
204 No Content

PUT Request in ASP.NET Core.
[HttpPut("{id}")]
public IActionResult UpdateProduct(int id, Product updatedProduct)
{
    if (id != updatedProduct.Id) return BadRequest();
    var existing = _repo.GetById(id);
    if (existing == null) return NotFound();

    _repo.Update(updatedProduct);
    return NoContent();
}

4. DELETE — Remove Resource

Purpose: Delete a resource by its ID
Idempotent: Deleting a non-existent item returns the same result
Status Code: 204 No Content, 404 Not Found

Example:
Request:
DELETE /api/products/1
ss
Response:
204 No Content

DELETE Request in ASP.NET Core:
[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
    var product = _repo.GetById(id);
    if (product == null) return NotFound();

    _repo.Delete(id);
    return NoContent();
}

What Does Idempotent Mean in REST APIs?

Idempotent refers to an operation that can be repeated multiple times without changing the result beyond the initial application.
In the context of REST APIs and HTTP methods, an idempotent method ensures that:
"No matter how many times a client sends the same request, the result on the server remains the same."


Simple Example:

✅ DELETE /api/products/1

  • First request: Deletes product with ID 1 → returns 204 No Content.
  • Second request: Product already deleted → returns 404 Not Found.

💡 But the server state hasn’t changed after the second call, so DELETE is idempotent.


Understanding GET, POST, PUT, and DELETE is essential when working with RESTful APIs in ASP.NET Core or any modern backend framework. Each HTTP method serves a specific purpose and follows well-defined rules, making your API clean, maintainable, and developer-friendly.

Difference Between Web API and MVC in ASP.NET Core.

ASP.NET Core is a powerful framework developed by Microsoft that supports both Web APIs and MVC architecture. While they share many similarities in structure, configuration, and middleware, they serve different purposes and are used in distinct scenarios.

This article explains the key differences between ASP.NET Core Web API and ASP.NET Core MVC, their intended use cases, and how they are implemented.

What is ASP.NET Core MVC?

ASP.NET Core MVC (Model-View-Controller) is a framework for building dynamic web applications that return HTML views to the browser. It uses the MVC design pattern, where:
  • Model: Represents the application’s data and business logic.
  • View: Responsible for presenting the data (UI) to the user using Razor syntax.
  • Controller: Handles incoming HTTP requests, interacts with the model, and returns views or data.

Key Features of ASP.NET Core MVC
  • Built-in routing system (app.UseRouting(), MapControllerRoute)
  • Strong support for dependency injection
  • Tag Helpers and Razor views for dynamic HTML generation
  • Model binding and validation support
  • Supports RESTful API endpoints
  • Highly testable and modular architecture
Example Code:
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();  // Returns the "Index.cshtml" view
    }
}

View (Index.cshtml)
<h1>Welcome to ASP.NET Core MVC</h1>

Use Cases
  • Web portals and dashboards
  • Admin panels
  • E-commerce websites
  • Content Management Systems (CMS)

2. What is ASP.NET Core Web API?

ASP.NET Core Web API is designed for building HTTP-based RESTful services that return data only, usually in the form of JSON or XML. There are no views involved — only data exchange between client and server.

Key Features of ASP.NET Core Web API

  • Returns data instead of views
  • Lightweight and high-performance
  • Uses standard HTTP methods: GET, POST, PUT, DELETE
  • Built-in support for model binding, validation, dependency injection, and routing
  • Easily integrated with Swagger for API documentation

Use Case:
  • Backend services for mobile apps, SPAs (Angular/React), or microservices
  • Systems that require JSON-based APIs
  • Server-to-server communication
Example Code:

Step 1: Create a Model.
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}

Step 2: Create the Controller.
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private static List<Product> products = new List<Product>
    {
        new Product { Id = 1, Name = "Laptop", Price = 1200 },
        new Product { Id = 2, Name = "Phone", Price = 800 }
    };

    [HttpGet]
    public ActionResult<IEnumerable<Product>> GetAll()
    {
        return Ok(products);
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetById(int id)
    {
        var product = products.FirstOrDefault(p => p.Id == id);
        if (product == null)
            return NotFound();

        return Ok(product);
    }

    [HttpPost]
    public ActionResult AddProduct(Product newProduct)
    {
        products.Add(newProduct);
        return CreatedAtAction(nameof(GetById), new { id = newProduct.Id }, newProduct);
    }
}

Step 3: Configure the application (Program.cs)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers(); // Enables attribute routing for API

app.Run();

Testing the API
  • GET /api/products → Returns all products
  • GET /api/products/1 → Returns product with ID = 1
  • POST /api/products → Add a new product (via Postman or frontend)

ASP.NET Core Web API is ideal for building modern, scalable, and stateless RESTful services. It separates the UI from the logic and serves as the backend for many client apps.

Key Difference Between Web API and MVC in ASP.NET Core.

Aspect ASP.NET Core MVC ASP.NET Core Web API
Purpose Build dynamic web applications with UI Build RESTful services for data exchange
Output Returns HTML views using Razor Returns data like JSON or XML
View Engine Uses Razor (.cshtml) No view engine; returns data only
Return Type Returns View(), PartialView() Returns Ok(), NotFound(), Created(), etc.
[ApiController] attribute Not used Commonly used for automatic model binding and validation
Use Case Websites, Admin dashboards, CMS SPAs (Angular, React), Mobile apps, Microservices
Client Browsers that render HTML Frontend apps, Postman, mobile apps
HTTP Verbs Mainly GET and POST GET, POST, PUT, DELETE (RESTful)

While ASP.NET Core MVC and Web API share the same base framework and features like routing, middleware, and dependency injection, they serve different application layers. MVC is ideal for UI-based applications, whereas Web API is built for data exchange and service-based architectures.

DON'T MISS

Tech News
© all rights reserved
made with by AlgoLesson