0% found this document useful (0 votes)
52 views118 pages

Web Api

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
52 views118 pages

Web Api

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 118

ASP.

NET Core Web API – Basics


ASP.NET Core Web API allows you to build HTTP services that can be consumed by client-side applications like web
apps, mobile apps, or other APIs. It is cross-platform, high-performance, and widely used for building RESTful APIs.
Here’s an overview and practical implementation of the core concepts of ASP.NET Core Web API.

1. Introduction to ASP.NET Core Web API


ASP.NET Core is a free, open-source web framework developed by Microsoft to build modern, cloud-based, and
Internet-connected applications. Web APIs in ASP.NET Core are used to expose services that can be consumed over
the web using HTTP protocols.
Key Features:
Cross-platform: Works on Windows, macOS, and Linux.
Modular: Only include the required features, reducing the application size.
High performance: ASP.NET Core is optimized for performance, making it ideal for high-scale applications.
Dependency Injection: Built-in support for Dependency Injection to make code easier to test and maintain.

2. HTTP (HyperText Transport Protocol)


HTTP is the foundation of any web communication and is used to send and receive data over the internet. In the
context of Web APIs:
HTTP Methods:
GET: Retrieve data.
POST: Create data.
PUT: Update data.
DELETE: Remove data.
Request and Response:
Request headers (such as Content-Type , Authorization ) and response codes (like 200 OK , 404
Not Found , etc.).

RESTful API: APIs in ASP.NET Core follow the principles of REST (Representational State Transfer), which relies
on HTTP for communication and statelessness.

3. Environment Setup for ASP.NET Core Web API Development


To develop ASP.NET Core Web APIs, you need the following environment setup:
1. Install .NET Core SDK:
Download and install the .NET Core SDK from the official Microsoft .NET download page.
2. Install Visual Studio (Optional):
Visual Studio is recommended for ASP.NET Core development because it provides features like IntelliSense,
debugging tools, and project templates.
Make sure to install the ASP.NET and web development workload when setting up Visual Studio.
3. Install Postman (For Testing API):
Postman is a popular tool for testing APIs and sending HTTP requests to your Web API endpoints.

4. Creating ASP.NET Core Web API Project using .NET Core CLI
To create a new ASP.NET Core Web API using the .NET Core CLI, follow these steps:
1. Open the terminal (or command prompt).
2. Run the following command to create a new Web API project:
dotnet new webapi -n MyWebApi bash

3. Navigate to the project folder:


cd MyWebApi bash

4. Run the application:


dotnet run bash

By default, the Web API will run at http://localhost:5000 .

5. How to Test ASP.NET Core Web API Using Postman


Postman is a powerful tool to test and interact with Web APIs.
1. Open Postman and create a new request.
2. For a GET request to fetch data, enter the API URL like http://localhost:5000/api/values .
3. Choose the HTTP method (GET, POST, PUT, DELETE) depending on the action you want to test.
4. Click Send and check the response status and data returned.

6. Creating ASP.NET Core Web API Project in Visual Studio


1. Open Visual Studio.
2. Go to File > New > Project.
3. Select ASP.NET Core Web API template.
4. Choose the desired .NET version and configure project name and location.
5. Click Create and Visual Studio will set up the Web API project for you.

7. Default ASP.NET Core Web API Files and Folders


When you create an ASP.NET Core Web API, Visual Studio generates the following files:
Program.cs: The entry point for the application.
Startup.cs: Contains the app's configuration, services, middleware pipeline, and route settings.
Controllers: Folder for API controller classes. The controllers manage incoming HTTP requests and return data
(usually in JSON format).
appsettings.json: Configuration file used for settings like connection strings and application-specific
configurations.

8. Swagger API in ASP.NET Core Web API


Swagger is a tool for documenting and testing Web APIs. In ASP.NET Core, it can be easily integrated using
Swashbuckle.
Steps to Enable Swagger in ASP.NET Core:
1. Install Swashbuckle NuGet Package:
dotnet add package Swashbuckle.AspNetCore bash

2. Modify Startup.cs to include Swagger services and middleware:


In the ConfigureServices method, add:
services.AddSwaggerGen(); csharp

In the Configure method, add:


app.UseSwagger(); csharp
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V
1"));

3. Run the application, and Swagger UI should be available at http://localhost:5000/swagger .


9. Controllers in ASP.NET Core Web API
Controllers in ASP.NET Core Web API manage HTTP requests, and they are responsible for returning appropriate
responses to the client.
Example Controller:
using Microsoft.AspNetCore.Mvc; csharp

namespace MyWebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}

// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}

// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}

// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}

In this example:
The GET method retrieves a list of values.
The POST , PUT , and DELETE methods perform CRUD operations.

10. Models in ASP.NET Core Web API


Models represent the data structure used in the Web API, and they are typically used to transfer data between the
client and server.
Example Model:
namespace MyWebApi.Models csharp
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}

This model represents a Product entity with Id , Name , and Price properties. It can be used for CRUD
operations in the controller.
Example of Using Model in Controller:
[HttpPost] csharp
public IActionResult Post([FromBody] Product product)
{
if (product == null)
{
return BadRequest();
}

// Add product to the database (not implemented here)


return CreatedAtAction("Get", new { id = product.Id }, product);
}

Real-time Implementation of an ASP.NET Core Web API Project


Let’s summarize the steps with a real-time example of an ASP.NET Core Web API to manage Products .
1. Create a New Web API Project:
dotnet new webapi -n ProductApi bash
cd ProductApi
2. Create Product Model ( Models/Product.cs ):
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

3. Create Controller ( Controllers/ProductController.cs ):


[Route("api/[controller]")] csharp
[ApiController]
public class ProductController : ControllerBase
{
private static List<Product> _products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 1000 },
new Product { Id = 2, Name = "Smartphone", Price = 500 }
};

[HttpGet]
public IEnumerable<Product> Get()
{
return _products;
}

[HttpPost]
public IActionResult Post([FromBody] Product product)
{
_products.Add(product);
return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
}
}

4. Enable Swagger in Startup.cs to test API documentation.


5. Run the Application and Test with Postman or Swagger UI:
Access GET http://localhost:5000/api/product to get all products.
Use POST http://localhost:5000/api/product to create a new product.

Conclusion
ASP.NET Core Web API is an
essential tool for building modern RESTful web services. This training provides you with a foundational understanding
of the key concepts such as HTTP methods, routing, controllers, models, and Swagger. Additionally, by following this
structured approach, you can develop and test your own Web API projects effectively.

ASP.NET Core Web API – Routing


Routing in ASP.NET Core Web API determines how incoming HTTP requests are mapped to controller actions. It
defines how URL patterns are matched with corresponding controller methods and allows you to create RESTful URLs
for handling resources effectively.
Routing in ASP.NET Core Web API is highly flexible and allows various routing strategies, including attribute-based
routing, conventional routing, and more. Let's explore the essential features of routing in ASP.NET Core Web API,
along with their implementation.

1. Routing in ASP.NET Core Web API


Routing in ASP.NET Core Web API maps HTTP requests to controller actions based on the URL patterns. ASP.NET
Core uses attribute routing and conventional routing.
Attribute Routing: Defines routes directly on the action methods or controllers using route attributes like
[Route] or [HttpGet] .

Conventional Routing: Configured globally in Startup.cs , where a pattern is defined that matches controller
names, actions, and parameters.
Basic Routing Example
In this example, the routing is done via attribute routing, where the route is specified directly on the controller or
action.
// Controller csharp
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
// GET api/products
[HttpGet]
public IActionResult Get()
{
return Ok(new string[] { "Product1", "Product2" });
}

// GET api/products/5
[HttpGet("{id}")]
public IActionResult Get(int id)
{
return Ok($"Product {id}");
}
}
In this example:
api/products maps to Get() action, which returns all products.
api/products/{id} maps to Get(int id) action, which retrieves a specific product by ID.

2. Route Parameters and Query Strings in Routing


ASP.NET Core Web API allows route parameters and query strings to be used to capture data from the URL.
Route Parameters
Route parameters are parts of the URL that act as placeholders for values. They are defined within curly braces {}
and can be passed directly to the controller action as method parameters.
Example:
[Route("api/products/{id}")] csharp
public IActionResult Get(int id)
{
// Use the id parameter to fetch the product
return Ok($"Product {id}");
}

This will match any URL like api/products/5 and pass the value 5 to the id parameter.
Query Strings
Query strings are typically used for optional parameters. They follow the ? symbol in the URL.
Example:
[HttpGet] csharp
public IActionResult Get([FromQuery] string category)
{
return Ok($"Fetching products in category: {category}");
}

URL example: api/products?category=electronics


In this case, the query string category is mapped to the category parameter of the method.

3. Multiple URLs for a Single Resource in ASP.NET Core Web API


ASP.NET Core allows multiple URLs to map to the same resource, making your API more flexible. You can achieve this
by defining multiple routes for the same action method using attribute routing.
Example:
[Route("api/products")] csharp
public class ProductsController : ControllerBase
{
// Multiple URL mappings for the same resource
[HttpGet("list")]
[HttpGet("all")]
public IActionResult GetAllProducts()
{
return Ok(new string[] { "Product1", "Product2", "Product3" });
}
}

In this example:
Both GET api/products/list and GET api/products/all will invoke the GetAllProducts()
method and return the list of products.
This is particularly useful when you want to provide multiple ways to access the same resource.

4. Token Replacement in ASP.NET Core Web API Routing


ASP.NET Core Web API supports token replacement in routing, where values within curly braces {} are replaced by
actual values passed via the URL.
For instance:
[Route("api/products/{id:int}")] csharp
public IActionResult GetById(int id)
{
return Ok($"Product ID: {id}");
}

The route api/products/{id:int} expects an integer id to replace the {id} token.


If the URL is api/products/5 , the action GetById is invoked with id = 5 .
Token Types:
{id:int} : Only integers can replace id .

{id:guid} : Only GUIDs can replace id .

{id:datetime} : Only DateTime values can replace id .

5. Route Prefix in ASP.NET Core Web API Routing


You can define a route prefix on the controller to apply a common base URL to all actions in that controller. This is
particularly useful to reduce repetitive code.
Example:
[Route("api/[controller]")] csharp
public class ProductsController : ControllerBase
{
// GET api/products
[HttpGet]
public IActionResult GetAll()
{
return Ok(new string[] { "Product1", "Product2" });
}

// GET api/products/5
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
return Ok($"Product {id}");
}
}

In this case, the Route("api/[controller]") applies the prefix api/products to both actions, and the id
token can be appended to the URL for the second action.

6. Route Constraints in ASP.NET Core Web API


Route constraints allow you to enforce certain rules on route parameters, ensuring that they only match certain values
(like integer, string, GUID, etc.).
Basic Route Constraints Example
Here’s an example of applying a route constraint to ensure that only integers are passed in the id parameter:
[Route("api/products/{id:int}")] csharp
public IActionResult GetById(int id)
{
return Ok($"Product ID: {id}");
}

In this case, the {id:int} constraint ensures that only integer values can be passed in place of {id} .
Common Route Constraints:
int : Matches only integers.

guid : Matches only GUID values.

datetime : Matches only DateTime values.

alpha : Matches only alphabetic characters (A-Z, a-z).


bool : Matches boolean values ( true / false ).
minlength(length) : Enforces a minimum string length.

maxlength(length) : Enforces a maximum string length.

Example with multiple constraints:


[Route("api/products/{id:int:min(1)}")] csharp
public IActionResult GetById(int id)
{
return Ok($"Product ID: {id}");
}

Here, the id parameter must be an integer and greater than or equal to 1.

Real-time Example of Routing in ASP.NET Core Web API


Let’s build a simple ASP.NET Core Web API for Products , demonstrating all routing concepts.
Step 1: Create Model ( Models/Product.cs )
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

Step 2: Create Controller ( Controllers/ProductController.cs )


[Route("api/products")] csharp
[ApiController]
public class ProductsController : ControllerBase
{
private static List<Product> _products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 1000 },
new Product { Id = 2, Name = "Smartphone", Price = 500 }
};

// GET api/products
[HttpGet]
public IActionResult Get()
{
return Ok(_products);
}

// GET api/products/5
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
var product = _products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}

// GET api/products/cheap
[HttpGet("cheap")]
public IActionResult GetCheapProducts()
{
var cheapProducts = _products.Where(p => p.Price < 600).ToList();
return Ok(cheapProducts);
}

// GET api/products/search?name=laptop
[HttpGet("search")]
public IActionResult SearchByName([FromQuery] string name)
{
var products = _products.Where(p => p.Name.Contains(name, StringComparison.Ordi
nalIgnoreCase)).ToList();
return Ok(products);
}
}

Explanation:
1. Route Prefix: The [Route("api/products")] attribute sets the base route for all actions.
2. Route Parameters: The GetById method uses {id:int} to ensure only integers can be passed as the id .
3. Multiple URLs: The GetCheapProducts() action is mapped to both GET api/products/cheap and GET
api/products/search?name=laptop , showing different URL access points for the same resource.

4. Query String: The SearchByName() method demonstrates how to retrieve data using query parameters.
Step 3: Run and Test with Postman/Swagger
GET http://localhost:5000/api/products returns all products.
GET
http://localhost:5000/api/products/1 returns the product with ID 1.

GET http://localhost:5000/api/products/cheap returns products with price less than 600.


GET http://localhost:5000/api/products/search?name=laptop returns products whose name
contains "laptop".
Conclusion
Routing in ASP.NET Core Web API provides a robust and flexible way to handle HTTP requests, define how URLs map
to controller actions, and apply constraints and patterns to improve the API design. The examples above illustrate
basic and advanced routing concepts, empowering you to create RESTful APIs that are clean, scalable, and easy to
test.

ASP.NET Core Web API – Return Types and Status Codes


In ASP.NET Core Web API, return types and HTTP status codes play a crucial role in designing RESTful services. They
define how the server responds to the client's requests, both in terms of the data returned and the status of the
request.
1. Controller Action Return Types in ASP.NET Core Web API
Controller action methods in ASP.NET Core Web API can return various types depending on the result of the
operation. Some common return types include:
IActionResult : A general return type for an HTTP response, allowing you to return various status codes and
response types (like Ok() , NotFound() , etc.).
ActionResult<T> : Used when the response is an entity, providing more specific types like Ok<T> ,
NotFound<T> , etc.

IEnumerable<T> or List<T> : Commonly used to return collections of data.

T : Directly returning a data object, which can automatically be serialized to JSON by default.

Example:
public class ProductsController : ControllerBase csharp
{
[HttpGet]
public IActionResult GetProducts()
{
var products = new List<string> { "Product1", "Product2" };
return Ok(products); // Returns 200 OK with product list
}

[HttpGet("{id}")]
public ActionResult<string> GetProduct(int id)
{
if (id <= 0) return NotFound(); // Returns 404 Not Found
return Ok($"Product {id}");
}
}

2. HTTP Status Codes in ASP.NET Core Web API


Status codes are part of the HTTP response returned by the server. These codes help indicate the result of the
request and are categorized into five main groups:
1xx: Informational Responses
2xx: Successful Responses
3xx: Redirection Responses
4xx: Client Error Responses
5xx: Server Error Responses
ASP.NET Core Web API makes it easy to return appropriate status codes with the correct response.

3. HTTP Status Codes and Their Meaning


200 HTTP Status Code (OK)
The 200 OK status code indicates that the request was successful, and the server is returning the requested data.
Example:
public IActionResult Get() csharp
{
var products = new List<string> { "Product1", "Product2" };
return Ok(products); // Returns 200 OK
}

201 HTTP Status Code (Created)


The 201 Created status code indicates that a resource was successfully created on the server. This is often used
in POST requests where new data is being submitted.
Example:
[HttpPost] csharp
public IActionResult Create([FromBody] Product product)
{
// Assume the product is created in the database
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

This will return 201 Created with the new resource.


202 HTTP Status Code (Accepted)
The 202 Accepted status code indicates that the request has been accepted for processing, but the processing is
not complete yet. It's used for asynchronous operations.
Example:
[HttpPost("process")] csharp
public IActionResult StartProcessing()
{
// Start some background processing
return Accepted(); // Returns 202 Accepted
}

204 HTTP Status Code (No Content)


The 204 No Content status code indicates that the request was successful but there is no content to return (often
used with DELETE operations).
Example:
[HttpDelete("{id}")] csharp
public IActionResult DeleteProduct(int id)
{
// Assume the product was deleted
return NoContent(); // Returns 204 No Content
}

301 HTTP Status Code (Moved Permanently)


The 301 Moved Permanently status code indicates that the resource has been permanently moved to a new URL.
It’s used in redirection.
Example:
[HttpGet("old-url")] csharp
public IActionResult OldUrlRedirect()
{
return RedirectPermanent("/new-url"); // Returns 301 Moved Permanently
}

302 HTTP Status Code (Found)


The 302 Found status code indicates a temporary redirection. The resource is temporarily available at a different
URL.
Example:
[HttpGet("temporary-url")] csharp
public IActionResult TemporaryRedirect()
{
return Redirect("/temporary-url"); // Returns 302 Found
}

304 HTTP Status Code (Not Modified)


The 304 Not Modified status code indicates that the resource has not been modified since the last request,
meaning the client can use its cached version of the resource.
Example:
[HttpGet("data")] csharp
public IActionResult GetData()
{
var lastModified = DateTime.Now.AddDays(-1); // Example of last modified time
Response.Headers["Last-Modified"] = lastModified.ToString("R");

if (Request.Headers.ContainsKey("If-Modified-Since"))
{
var clientDate = DateTime.Parse(Request.Headers["If-Modified-Since"]);
if (clientDate >= lastModified)
{
return StatusCode(304); // Returns 304 Not Modified
}
}
return Ok("New Data");
}

400 HTTP Status Code (Bad Request)


The 400 Bad Request status code indicates that the client’s request is malformed or has invalid data.
Example:
[HttpPost] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
if (product == null || string.IsNullOrEmpty(product.Name))
{
return BadRequest("Invalid product data."); // Returns 400 Bad Request
}
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

401 HTTP Status Code (Unauthorized)


The 401 Unauthorized status code indicates that the client is not authenticated to access the resource.
Example:
[HttpGet("restricted")] csharp
[Authorize] // Requires authentication
public IActionResult RestrictedData()
{
return Ok("This is restricted data.");
}

If the client is not authenticated, they will receive a 401 Unauthorized response.
403 HTTP Status Code (Forbidden)
The 403 Forbidden status code indicates that the client does not have permission to access the resource, even if
authenticated.
Example:
[HttpGet("admin")] csharp
[Authorize(Roles = "Admin")]
public IActionResult AdminData()
{
return Ok("Admin-only data.");
}

If the user does not have the Admin role, a 403 Forbidden status is returned.
404 HTTP Status Code (Not Found)
The 404 Not Found status code indicates that the requested resource could not be found on the server.
Example:
[HttpGet("{id}")] csharp
public IActionResult GetProduct(int id)
{
var product = _products.FirstOrDefault(p => p.Id == id);
if (product == null)
{
return NotFound(); // Returns 404 Not Found
}
return Ok(product);
}

405 HTTP Status Code (Method Not Allowed)


The 405 Method Not Allowed status code indicates that the HTTP method used is not allowed for the requested
resource.
Example:
[HttpPost] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
return Ok(product);
}

// If a client sends a GET request to this endpoint, it will return 405 Method Not Allo
wed

500 HTTP Status Code (Internal Server Error)


The 500 Internal Server Error status code indicates that an unexpected error occurred on the server.
Example:
[HttpGet("error")] csharp
public IActionResult SimulateError()
{
throw new Exception("An unexpected error occurred.");
return StatusCode(500); // Returns 500 Internal Server Error
}

501 HTTP Status Code (Not Implemented)


The 501 Not Implemented status code indicates that the server does not support the functionality required to
fulfill the request.
Example:
[HttpGet("notimplemented")] csharp
public IActionResult NotImplemented()
{
return StatusCode(501); // Returns 501 Not Implemented
}

503 HTTP Status Code (Service Unavailable)


The 503 Service Unavailable status code indicates that the server is temporarily unavailable, usually due to
maintenance or overloading.
Example:
[HttpGet("maintenance")] csharp
public IActionResult Maintenance()
{
return StatusCode(503, "Service temporarily unavailable due to maintenance."); // R
eturns 503 Service Unavailable
}

504 HTTP Status Code (Gateway Timeout)


The 504 Gateway Timeout status code indicates that a gateway or proxy server timed out while waiting for a
response from an upstream server.
Example:
[HttpGet("timeout")] csharp
public IActionResult Timeout()
{
// Simulate timeout scenario
return StatusCode(504); // Returns 504 Gateway Timeout
}

4. Configure Allowed HTTP Methods Globally in ASP.NET Core Web API


ASP.NET Core allows you to configure which HTTP methods are allowed globally via middleware. For example, you can
restrict the allowed methods using the UseCors middleware or by adding the HttpMethod constraints in your
controller.
Example in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificMethods", builder =>
{
builder.WithMethods("GET", "POST");
});

}); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseCors("AllowSpecificMethods"); }

---

### **Conclusion**

Understanding the various HTTP status codes and their usage in ASP.NET Core Web API is
essential for building effective RESTful APIs. By using appropriate status codes for di
fferent actions, you help clients understand the outcome of their requests. Additionall
y, you can control the flow of your application, implement secure access, handle errors
gracefully, and ensure proper routing of HTTP requests.

Model Binding in ASP.NET Core Web API


Model binding in ASP.NET Core Web API is the process of mapping data from an HTTP request (such as form data,
query strings, request body, headers, etc.) to a C# model. It enables developers to easily retrieve data from incoming
HTTP requests and pass it to action methods in controllers. ASP.NET Core uses different attributes to bind data from
various sources like form, query, route, headers, and body.
1. Model Binding using FromForm in ASP.NET Core Web API
The FromForm attribute binds data from the form (i.e., the request body in case of a POST request) to a model. It
is typically used for form submissions, where the content type is application/x-www-form-urlencoded or
multipart/form-data .

Example:
[HttpPost("create")] csharp
public IActionResult CreateProduct([FromForm] Product product)
{
// The product will be populated from the form data
return Ok(product);
}

Here, when a user submits a form with data, the Product model will be populated with the form data.

2. Model Binding using FromQuery in ASP.NET Core Web API


The FromQuery attribute is used to bind data from query string parameters in the URL. This is useful when data is
passed through the URL.
Example:
[HttpGet("getProduct")] csharp
public IActionResult GetProduct([FromQuery] int id)
{
var product = _productService.GetProductById(id);
return Ok(product);
}

If the URL is https://api.example.com/getProduct?id=1 , the value 1 will be passed to the id parameter.

3. Model Binding using FromRoute in ASP.NET Core Web API


The FromRoute attribute is used to bind data from route parameters. This is useful when parameters are passed as
part of the URL path.
Example:
[HttpGet("product/{id}")] csharp
public IActionResult GetProductById([FromRoute] int id)
{
var product = _productService.GetProductById(id);
return Ok(product);
}

For the URL https://api.example.com/product/1 , the value 1 will be used to bind the id parameter.

4. Model Binding using FromHeader in ASP.NET Core Web API


The FromHeader attribute binds data from the HTTP request headers. This is useful for passing metadata or tokens,
like authentication tokens, through headers.
Example:
[HttpGet("getHeaderData")] csharp
public IActionResult GetHeaderData([FromHeader] string authorization)
{
// The authorization header will be mapped to the 'authorization' parameter
return Ok(new { Authorization = authorization });
}

Here, if the request includes a header Authorization: Bearer token_value , it will be passed to the
authorization parameter.

5. Model Binding using FromBody in ASP.NET Core Web API


The FromBody attribute binds data from the request body. It is commonly used in POST or PUT requests to map
complex objects sent as JSON or XML.
Example:
[HttpPost("create")] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
// The product will be populated from the request body (JSON or XML)
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product);
}

Here, the data from the request body (in JSON or XML format) will be deserialized into the Product object.

6. Custom Model Binding in ASP.NET Core Web API


Custom model binding allows you to create your own logic for binding data from the request to a model. This can be
useful when the default binding behavior doesn't meet your needs.
To implement custom model binding, create a class that implements the IModelBinder interface and register it in
the Startup.cs .
Example:
public class CustomProductBinder : IModelBinder csharp
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var productId = bindingContext.HttpContext.Request.Query["productId"];
var product = _productService.GetProductById(productId);
bindingContext.Result = ModelBindingResult.Success(product);
return Task.CompletedTask;
}
}

Now, use this custom model binder in the controller action method:
[HttpGet("getProduct")] csharp
public IActionResult GetProduct([ModelBinder(BinderType = typeof(CustomProductBinder))]
Product product)
{
return Ok(product);
}

7. How to Apply Binding Attributes to Model Properties in ASP.NET Core Web API
You can use attributes like FromQuery , FromBody , FromHeader , and FromForm on individual model
properties to control where each property is bound from. This is useful when a model contains multiple properties that
come from different parts of the request.
Example:
public class Product csharp
{
[FromQuery]
public int Id { get; set; }

[FromBody]
public string Name { get; set; }

[FromHeader]
public string Authorization { get; set; }
}
In this example, the Id will be taken from the query string, Name from the body, and Authorization from the
header.

8. Content Negotiation in ASP.NET Core Web API


Content negotiation in ASP.NET Core Web API allows the server to decide which format to return based on the
Accept header sent by the client. It supports several media types such as JSON, XML, and others.

Example:
[HttpGet] csharp
public IActionResult GetProduct()
{
var product = new Product { Id = 1, Name = "Laptop" };
return Ok(product); // The response format will depend on the Accept header.
}

If the Accept header is application/json , the response will be in JSON format.


You can configure the supported formats in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddControllers()
.AddXmlDataContractSerializerFormatters(); // To support XML format
}

9. Include and Exclude Properties from Model Binding in ASP.NET Core Web API
To control which properties of a model are bound or excluded from model binding, you can use attributes like Bind
and JsonIgnore .
[Bind] : Allows you to specify which properties are bound in a model.

[JsonIgnore] : Excludes a property from being serialized or deserialized.

Example:
public class Product csharp
{
[BindRequired]
public int Id { get; set; }

[JsonIgnore]
public string InternalNotes { get; set; }
}

In this example:
Id is required for model binding.

InternalNotes is ignored during both serialization and deserialization.

You can also use the [Bind] attribute to allow binding only specific properties:
public class Product csharp
{
public int Id { get; set; }

[Bind("Name")]
public string Name { get; set; }
}

In this case, only the Name property will be bound, while other properties like Id will not.

Summary
Model Binding is the process of binding data from various parts of the HTTP request (query strings, route
parameters, headers, form data, body) to C# model properties.
Binding Attributes such as FromQuery , FromBody , FromRoute , FromHeader , FromForm are used to
specify where each property should be bound from.
Custom Model Binding can be implemented when the default model binding behavior does not meet the
requirements of your application.
Content Negotiation allows your API to return data in multiple formats (e.g., JSON, XML) based on the client's
Accept header.

Binding Constraints like [Bind] and [JsonIgnore] help control which properties can or cannot be bound
during model binding.
These features in ASP.NET Core Web API provide flexibility to handle various input scenarios in a clean and efficient
way, making your API more adaptable to different client needs.

AutoMapper in ASP.NET Core Web API


AutoMapper is a popular object-to-object mapping library used to simplify the mapping of one object to another. In
ASP.NET Core Web API, AutoMapper is commonly used to map data between entity models and DTOs (Data Transfer
Objects) in a clean and efficient manner, thereby reducing the need for boilerplate code.
AutoMapper is especially useful when dealing with complex object mappings and when you need to separate
concerns by having separate models for data transfer (DTO) and data persistence (entities).
1. Setting Up AutoMapper in ASP.NET Core Web API
To get started with AutoMapper, you need to install the AutoMapper NuGet package and configure it in your
application.
Install AutoMapper via NuGet:
Install-Package AutoMapper bash

Configure AutoMapper in Startup.cs or Program.cs (ASP.NET Core 6 or later):


public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAutoMapper(typeof(Startup)); // Add AutoMapper to the DI container
services.AddControllers();
}

2. AutoMapper Complex Mapping in ASP.NET Core Web API


You can use AutoMapper to map complex objects. For example, mapping an Order entity to a OrderDTO , which
might contain a subset of properties or differently structured properties.
Example:
public class Order csharp
{
public int OrderId { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
}

public class OrderDTO


{
public int Id { get; set; }
public string Product { get; set; }
public decimal TotalPrice { get; set; }
}

// AutoMapper Profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Order, OrderDTO>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.OrderId))
.ForMember(dest => dest.Product, opt => opt.MapFrom(src => src.ProductNam
e))
.ForMember(dest => dest.TotalPrice, opt => opt.MapFrom(src => src.Price));
}
}

Now you can use AutoMapper to map between Order and OrderDTO .

3. Mapping Complex Type to Primitive Type using AutoMapper in ASP.NET Core Web API
AutoMapper also supports mapping complex types (like classes or collections) to primitive types (like strings, ints,
etc.).
Example:
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
}

public class ProductDTO


{
public string ProductName { get; set; }
}

// AutoMapper Profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Product, string>() // Mapping Product to string (Name)
.ConvertUsing(src => src.Name);
}
}

In this example, the Product class is mapped to just the Name property, which is a string.

4. AutoMapper Reverse Mapping in ASP.NET Core Web API


AutoMapper supports reverse mapping, meaning you can map in both directions between source and destination
types. This is helpful when you need to update a model based on a DTO.
Example:
public class Order csharp
{
public int OrderId { get; set; }
public string ProductName { get; set; }
}
public class OrderDTO
{
public int Id { get; set; }
public string Product { get; set; }
}

// AutoMapper Profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Order, OrderDTO>()
.ReverseMap(); // Enable reverse mapping
}
}

Now, you can map from Order to OrderDTO and vice versa using AutoMapper.

5. AutoMapper Conditional Mapping in ASP.NET Core Web API


AutoMapper allows conditional mapping where you can define conditions to control when a particular property should
be mapped.
Example:
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public decimal? Price { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
public string Price { get; set; }
}

public class MappingProfile : Profile


{
public MappingProfile()
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Price, opt => opt.Condition(src => src.Price.HasVal
ue))
.ForMember(dest => dest.Price, opt => opt.MapFrom(src => src.Price.HasValue
? src.Price.ToString("C") : "N/A"));
}
}

In this example, Price will be mapped only if it has a value; otherwise, it will be set to "N/A".

6. AutoMapper Condition, PreCondition, and PostCondition in ASP.NET Core Web API


AutoMapper allows additional flexibility with conditions by allowing Condition , PreCondition , and
PostCondition to be applied to the mapping.

Condition : Apply conditions for the mapping itself.

PreCondition : Apply conditions before the mapping.

PostCondition : Apply conditions after the mapping.

Example:
public class Product csharp
{
public string Name { get; set; }
public decimal Price { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
public decimal Price { get; set; }
}

public class MappingProfile : Profile


{
public MappingProfile()
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Price, opt => opt.PreCondition(src => src.Price >
0)) // Only map if price > 0
.ForMember(dest => dest.Name, opt => opt.PostCondition(src => !string.IsNul
lOrEmpty(src.Name))); // Ensure Name is not empty
}
}

Here, PreCondition and PostCondition ensure that the price is positive and the name is not empty before
mapping.

7. Ignore Property Mapping using AutoMapper in ASP.NET Core Web API


You can use the ForMember method to ignore a property from being mapped.
Example:
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
public decimal Price { get; set; }
}

public class MappingProfile : Profile


{
public MappingProfile()
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Name, opt => opt.Ignore()); // Ignore the Name prop
erty
}
}

In this example, the Name property is excluded from being mapped.

8. AutoMapper Null Substitution in ASP.NET Core Web API


AutoMapper allows you to specify a default value if a property is null during mapping.
Example:
public class Product csharp
{
public string Name { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
}

public class MappingProfile : Profile


{
public MappingProfile()
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Name, opt => opt.NullSubstitute("Unknown"));
}
}

In this case, if the Name property is null, it will be replaced with "Unknown" during mapping.

9. Fixed, Dynamic, Null Substitution, and Ignore Property Mapping using AutoMapper
You can combine various features of AutoMapper, such as fixed values, dynamic values, null substitution, and ignoring
properties, in one mapping configuration.
Example:
public class Product csharp
{
public string Name { get; set; }
public decimal Price { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
public decimal Price { get; set; }
}

public class MappingProfile : Profile


{
public MappingProfile()
{
CreateMap<Product, ProductDTO>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name ?? "Defaul
t Name")) // Use dynamic or default value for Name
.ForMember(dest => dest.Price, opt => opt.NullSubstitute(0)) // Substitute
null Price with 0
.ForMember(dest => dest.Name, opt => opt.Ignore()); // Ignore Name property
}
}

In this example, the Name property is ignored, while Price will use null substitution, and Name will default to
"Default Name" if it is null.

10. AutoMapper Real-time Example in ASP.NET Core Web API


AutoMapper is commonly used in real-world applications where data transfer objects (DTOs) are used to separate the
structure of data being sent to and received from a client, versus the structure used in the backend database (entity
models). Here's a real-time example for a product service.
Example:
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

public class ProductDTO


{
public string Name { get; set; }
public decimal Price { get; set; }
}

// AutoMapper Profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap

<Product, ProductDTO>(); } }
// Product Controller [Route("api/[controller]")] public class ProductsController : ControllerBase { private readonly
IProductService productService; private readonly IMapper mapper;
public ProductsController(IProductService productService, IMapper mapper)
{
_productService = productService;
_mapper = mapper;
}

[HttpGet("{id}")]
public ActionResult<ProductDTO> GetProduct(int id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound();
}

var productDTO = _mapper.Map<ProductDTO>(product);


return Ok(productDTO);
}

In this real-world example, `ProductDTO` is used to send data from the API to the clien
t, while `Product` is the entity model that is used for database operations. AutoMapper
simplifies the transformation between the two objects.

---

### **Summary**

AutoMapper in ASP.NET Core Web API simplifies the process of mapping between different
object models (such as DTOs and entities). Key features include:

- **Complex mapping**: Mapping objects with different structures.


- **Reverse mapping**: Mapping in both directions.
- **Conditional mapping**: Apply conditions for when a property should be mapped.
- **Null substitution**: Provide default values when a property is null.
- **Ignore properties**: Exclude properties from mapping.
- **Real-time example**: Mapping entities to DTOs for API responses.

By using AutoMapper, you can reduce boilerplate code and improve maintainability, espec
ially when dealing with complex object transformations.

HTTP Methods in ASP.NET Core Web API


In ASP.NET Core Web API, HTTP methods (or HTTP verbs) represent the actions that can be performed on resources
exposed by the web service. The most common HTTP methods include GET, POST, PUT, DELETE, PATCH, and others,
which are used to retrieve, create, update, delete, and partially update resources, respectively.
These methods correspond to CRUD operations (Create, Read, Update, Delete) and are used in the routing of Web
API endpoints.

1. HTTP GET Method in ASP.NET Core Web API


The GET method is used to retrieve data from the server. It does not modify the server state. In ASP.NET Core Web
API, it is typically used to get resource(s) from a database.
Example:
[HttpGet] csharp
public IActionResult GetAllProducts()
{
var products = _productService.GetAll();
return Ok(products);
}

Here, the GetAllProducts method retrieves all products from the service and returns them with an HTTP 200 OK
status.
HTTP GET Query Parameters: You can also handle query parameters by adding them as method parameters:
[HttpGet] csharp
public IActionResult GetProductById(int id)
{
var product = _productService.GetById(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}

2. HTTP POST Method in ASP.NET Core Web API


The POST method is used to create a new resource on the server. It usually involves submitting data from a client to
the server, which then processes the request and adds the resource to the database.
Example:
[HttpPost] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
if (product == null)
{
return BadRequest();
}
_productService.Add(product);
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product);
}

Here, the CreateProduct method adds a new product to the service and returns HTTP 201 Created along with the
URI of the newly created resource.

3. HTTP PUT Method in ASP.NET Core Web API


The PUT method is used to update an existing resource or replace the resource at the specified URI. If the resource
does not exist, it may create a new one, though this is often considered a design choice.
Example:
[HttpPut("{id}")] csharp
public IActionResult UpdateProduct(int id, [FromBody] Product product)
{
if (product == null || id != product.Id)
{
return BadRequest();
}

var existingProduct = _productService.GetById(id);


if (existingProduct == null)
{
return NotFound();
}

_productService.Update(product);
return NoContent();
}

Here, the UpdateProduct method updates the existing product identified by id and returns HTTP 204 No
Content.

4. HTTP PATCH Method in ASP.NET Core Web API


The PATCH method is used to update a resource partially, meaning only the fields that are provided in the request
body will be updated.
Example:
[HttpPatch("{id}")] csharp
public IActionResult PartiallyUpdateProduct(int id, [FromBody] JsonPatchDocument<Produc
t> patchDocument)
{
var product = _productService.GetById(id);
if (product == null)
{
return NotFound();
}

patchDocument.ApplyTo(product);
_productService.Update(product);
return Ok(product);
}

Here, the PartiallyUpdateProduct method applies a JSON Patch document to update specific fields of the
product.

5. HTTP DELETE Method in ASP.NET Core Web API


The DELETE method is used to delete a resource identified by a given URI.
Example:
[HttpDelete("{id}")] csharp
public IActionResult DeleteProduct(int id)
{
var product = _productService.GetById(id);
if (product == null)
{
return NotFound();
}

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

In this example, the DeleteProduct method deletes a product from the database and returns HTTP 204 No
Content.

6. HTTP HEAD Method in ASP.NET Core Web API


The HEAD method is similar to the GET method, but it does not return the body of the resource, only the headers.
It's useful when you only want metadata about a resource (like headers), such as checking if a resource exists without
downloading it.
Example:
[HttpHead("{id}")] csharp
public IActionResult CheckProductExistence(int id)
{
var product = _productService.GetById(id);
if (product == null)
{
return NotFound();
}
return Ok();
}

Here, the CheckProductExistence method checks if the resource exists, but no body is returned, just the headers.

7. HTTP OPTIONS Method in ASP.NET Core Web API


The OPTIONS method is used to describe the communication options for the target resource. It can be used to find
out which HTTP methods are supported for a particular resource.
Example:
[HttpOptions] csharp
public IActionResult GetAllowedMethods()
{
return Ok("Allowed methods: GET, POST, PUT, DELETE");
}

Here, the GetAllowedMethods method informs the client of the allowed HTTP methods for a particular resource.

Logging in ASP.NET Core Web API


Logging is essential for monitoring, debugging, and auditing. ASP.NET Core provides built-in logging that supports
various providers like the console, file, and database logging.
How to Implement Serilog in ASP.NET Core Web API
Step 1: Install the required NuGet packages:
Install-Package Serilog.AspNetCore bash
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File

Step 2: Configure Serilog in Program.cs or Startup.cs :


using Serilog; csharp

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureLogging((context, logging) =>
{
logging.ClearProviders();
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog(); // Add Serilog

Step 3: Set up Serilog's sinks:


Log.Logger = new LoggerConfiguration() csharp
.WriteTo.Console()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();

Now, Serilog will log messages to both the console and a file.
Logging to Database using Serilog in ASP.NET Core Web API
You can also log messages to a database by using the Serilog.Sinks.MSSqlServer package.
Step 1: Install the required NuGet package:
Install-Package Serilog.Sinks.MSSqlServer bash

Step 2: Configure logging to SQL Server:


Log.Logger = new LoggerConfiguration() csharp
.WriteTo.MSSqlServer(connectionString, "Logs")
.CreateLogger();

This writes logs to the Logs table in the configured SQL Server database.

How to Implement Logging using NLog in ASP.NET Core Web API


Step 1: Install the required NuGet packages:
Install-Package NLog.Web.AspNetCore bash
Install-Package NLog

Step 2: Configure NLog in Program.cs :


public static IHostBuilder CreateHostBuilder(string[] args) => csharp
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
}).UseNLog();
});

Step 3: Set up NLog configuration in nlog.config :


<?xml version="1.0" encoding="utf-8" ?> xml
<nlog xmlns="http://nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/200
1/XMLSchema-instance">
<targets>
<target xsi:type="File" name="logfile" fileName="logs/logfile.txt" />
<target xsi:type="Console" name="logconsole" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile,logconsole" />
</rules>
</nlog>

Logging to Database using NLog in ASP.NET Core Web API


Step 1: Install the NLog and NLog.Web NuGet packages:
Install-Package NLog.Web.AspNetCore bash
Install-Package NLog.Database

Step 2: Configure logging to the database in nlog.config :


<target xsi:type="Database" name="database" connectionString="YourConnectionString" com
xml
mandText="INSERT INTO Logs (LogDate, Level, Message) VALUES (@LogDate, @Level, @Messag
e)">
<parameter name="@LogDate" layout="${longdate}" />
<parameter name="@Level" layout="${level}" />
<parameter name="@Message" layout="${message}" />
</target>

**Serilog vs NLog in ASP.NET Core Web


API**
Both Serilog and NLog are widely used logging frameworks in ASP.NET Core.
Key Differences:
Serilog: Known for its structured logging. Allows you to log events as structured data (JSON), which is useful for
querying logs in large-scale systems.
NLog: Known for being highly configurable and supports more output targets (like databases, files, etc.) with
extensive configuration options.
Both logging libraries are capable of logging to various sources, but you might choose one over the other based on
your needs for structured logs, scalability, or ease of configuration.
Caching in ASP.NET Core
Caching in ASP.NET Core improves the performance and scalability of web applications by storing copies of frequently
accessed data in memory or other distributed systems. This reduces the load on databases and increases the
response time for users.
ASP.NET Core provides several caching strategies:
In-Memory Caching
Distributed Caching (using Redis, NCache, SQL Server, etc.)
Response Caching
Each of these strategies is suitable for different scenarios based on the application's requirements.

1. In-Memory Caching in ASP.NET Core


In-Memory Caching stores data in memory on the web server. It is useful for scenarios where data needs to be
cached temporarily during the lifespan of a single server session. The cached data is stored locally in the memory of
the web server, which means it is not shared across multiple server instances in a load-balanced environment.
Implementation:
1. Install the necessary NuGet package: In-memory caching is part of the Microsoft.Extensions.Caching.Memory
package, which is usually already included in ASP.NET Core.
2. Configure In-Memory Caching in Startup.cs : In the ConfigureServices method of Startup.cs , add
the caching services.
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddMemoryCache(); // Registering In-Memory Cache
}

3. Using In-Memory Cache: Inject IMemoryCache into your controllers or services to use it.
public class ProductService csharp
{
private readonly IMemoryCache _memoryCache;

public ProductService(IMemoryCache memoryCache)


{
_memoryCache = memoryCache;
}

public Product GetProduct(int id)


{
if (!_memoryCache.TryGetValue(id, out Product product))
{
product = GetProductFromDatabase(id); // Database call
_memoryCache.Set(id, product, TimeSpan.FromMinutes(5)); // Cache the re
sult for 5 minutes
}
return product;
}
}
2. Customize In-Memory Cache in ASP.NET Core
In-memory cache behavior can be customized by setting cache entry options like expiration, priority, and sliding
expiration.
Example:
public void CacheProduct(int productId, Product product) csharp
{
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(10)) // Sliding expiration
.SetAbsoluteExpiration(TimeSpan.FromHours(1)) // Absolute expiration
.SetPriority(CacheItemPriority.Normal); // Cache item priority

_memoryCache.Set(productId, product, cacheEntryOptions);


}

3. How to Implement Redis Cache in ASP.NET Core


Redis is a popular distributed caching system that allows caching across multiple servers in a distributed environment.
It's ideal for scenarios where you have multiple instances of your application (in a load-balanced or cloud
environment).
Steps for Implementing Redis Cache:
1. Install the necessary NuGet package: You need to install the
Microsoft.Extensions.Caching.StackExchangeRedis package to use Redis caching.

Install-Package Microsoft.Extensions.Caching.StackExchangeRedis bash

2. Configure Redis in Startup.cs : In the ConfigureServices method, register Redis as a distributed cache.
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379"; // Redis server address
options.InstanceName = "SampleInstance"; // Name of the Redis instance
});
}

3. Using Redis Cache: Inject IDistributedCache into your service or controller.


public class ProductService csharp
{
private readonly IDistributedCache _cache;

public ProductService(IDistributedCache cache)


{
_cache = cache;
}

public async Task<Product> GetProductAsync(int productId)


{
var product = await _cache.GetStringAsync(productId.ToString());
if (product == null)
{
// Get product from database if not in cache
product = await GetProductFromDatabaseAsync(productId);
await _cache.SetStringAsync(productId.ToString(), product, new Distribu
tedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
}
return product;
}
}

4. In-Memory Caching vs Distributed Caching in ASP.NET Core


Feature In-Memory Caching Distributed Caching
Scope Local to the server Available across multiple servers
Use Case Single server applications Multi-server (load balanced) applications
Data Only available on the local server Available to all servers in the cluster
Availability
Scaling Not suitable for scaling across multiple Scalable across multiple application
instances instances
Caching Engine Stored in RAM of the server Redis, NCache, SQL Server, etc.
In-memory caching is simpler to implement and works well for single-server applications, while distributed caching
like Redis is essential for scaling applications across multiple servers.

5. NCache Cluster and Its Types in Distributed Caching


NCache is a popular distributed caching platform for .NET applications. It can store large datasets and supports
clustering for scalability.
NCache Cluster Types:
1. Partitioned Cluster: Distributes the data across different cache servers.
2. Replicated Cluster: Data is replicated across all servers in the cluster to ensure high availability.
3. Mirror Cluster: Data is mirrored between the primary and backup cache servers.

6. How to Download and Install NCache in Windows


1. Download NCache: Visit the NCache official website and download the latest version of NCache.
2. Install NCache: Run the installer and follow the instructions. You can install NCache as a standalone or cluster-
based cache depending on your setup.
3. Start NCache: After installation, you can start the NCache server via the command line or use NCache Manager
for a graphical interface.

7. How to Implement NCache in ASP.NET Core Web API


To use NCache with ASP.NET Core, you need to install the NCache client and configure it in your application.
Steps:
1. Install NCache NuGet Package:
Install-Package Alachisoft.NCache.Web bash

2. Configure NCache in Startup.cs :


public void ConfigureServices(IServiceCollection services) csharp
{
services.AddNCacheDistributedCache(options =>
{
options.CacheName = "MyCache"; // NCache cluster name
});
}

3. Using NCache in Services:


public class ProductService csharp
{
private readonly IDistributedCache _cache;

public ProductService(IDistributedCache cache)


{
_cache = cache;
}

public async Task<Product> GetProductAsync(int productId)


{
var product = await _cache.GetStringAsync(productId.ToString());
if (product == null)
{
product = await GetProductFromDatabaseAsync(productId);
await _cache.SetStringAsync(productId.ToString(), product, new Distribu
tedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
}
return product;
}
}

8. Response Caching in ASP.NET Core Web API


Response Caching improves performance by caching the response of HTTP requests and serving it for subsequent
requests, reducing the processing time on the server.
Enable Response Caching:
1. Install the Response Caching Middleware:
Install-Package Microsoft.AspNetCore.ResponseCaching bash

2. Configure Response Caching in Startup.cs : Add the AddResponseCaching method in


ConfigureServices :

public void ConfigureServices(IServiceCollection services) csharp


{
services.AddResponseCaching();
}

3. Use Response Caching in the Controller: You can apply the ResponseCache attribute to your controller or
actions.
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client, NoStore =csharp
fa
lse)]
public IActionResult GetProduct(int id)
{
var product = _productService.GetById(id);
return Ok(product);
}
This example caches the response for 60 seconds.

By understanding these caching strategies, you can choose the most suitable one for your application, whether it's in-
memory caching for simple scenarios or distributed caching like Redis or NCache for scalable, multi-server
applications.

Fluent API Validation in ASP.NET Core Web API


Fluent API Validation in ASP.NET Core is a powerful way to enforce data validation rules for your models using the
FluentValidation library. FluentValidation allows for complex, readable, and maintainable validation logic using a
fluent interface (method chaining) that integrates seamlessly with ASP.NET Core's model binding.

1. Fluent API Validation in ASP.NET Core Web API


FluentValidation is an open-source validation library that allows developers to build complex validation rules for
models in a fluent manner. It provides an alternative to the traditional data annotation-based validation.
Setup FluentValidation:
1. Install FluentValidation NuGet Package: To use FluentValidation, you must first install the
FluentValidation.AspNetCore NuGet package:

Install-Package FluentValidation.AspNetCore bash

2. Configure FluentValidation in Startup.cs: In your Startup.cs file, you need to add FluentValidation services
to the dependency injection container.
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddControllers()
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<
Startup>());
}

3. Create a Validator Class: Next, create a validator class that contains the validation rules for your model.
public class ProductValidator : AbstractValidator<Product> csharp
{
public ProductValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Product name is required.");
RuleFor(x => x.Price).GreaterThan(0).WithMessage("Price must be greater tha
n zero.");
RuleFor(x => x.Description).MaximumLength(200).WithMessage("Description ca
n't exceed 200 characters.");
}
}

4. Apply Fluent Validation to Models: Now, when you pass a model to an action method, FluentValidation will
automatically validate it:
[HttpPost] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

// Process the product...


return Ok();
}

The ProductValidator class ensures that the Product model is validated according to the specified rules.

2. Fluent API Async Validators in ASP.NET Core Web API


FluentValidation also supports asynchronous validation for scenarios where the validation depends on data outside
of the model (such as querying a database or an external service).
Async Validator Example:
In this example, we will create an asynchronous validator to check if a product name already exists in the database.
public class ProductValidator : AbstractValidator<Product> csharp
{
private readonly IProductService _productService;

public ProductValidator(IProductService productService)


{
_productService = productService;

RuleFor(x => x.Name)


.NotEmpty().WithMessage("Product name is required.")
.MustAsync(BeUniqueName).WithMessage("Product name already exists.");
}

private async Task<bool> BeUniqueName(string productName, CancellationToken cancell


ationToken)
{
var existingProduct = await _productService.GetProductByNameAsync(productName);
return existingProduct == null;
}
}

In this case, BeUniqueName is an asynchronous method that queries the database to check if a product name
already exists. This method is used with the MustAsync validation rule.

3. Fluent API Custom Validators in ASP.NET Core Web API


You can create custom validators using the Custom method provided by FluentValidation. This method allows you
to define your own validation logic.
Custom Validator Example:
Suppose you want to validate that the product's price is not only greater than 0 but also must be a valid multiple of 5.
You can write a custom validator for this:
public class ProductValidator : AbstractValidator<Product> csharp
{
public ProductValidator()
{
RuleFor(x => x.Price)
.GreaterThan(0).WithMessage("Price must be greater than zero.")
.Custom((price, context) =>
{
if (price % 5 != 0)
{
context.AddFailure("Price must be a multiple of 5.");
}
});
}
}

In this example, the Custom method allows you to write custom logic to validate the price of the product.

4. Fluent API Conditional Validations in ASP.NET Core Web API


FluentValidation allows for conditional validations, where you can validate a property based on the value of another
property or certain conditions.
Conditional Validation Example:
In the following example, we validate a Discount only if the IsDiscounted property is set to true .
public class ProductValidator : AbstractValidator<Product> csharp
{
public ProductValidator()
{
RuleFor(x => x.IsDiscounted)
.Equal(true).When(x => x.Discount > 0)
.WithMessage("Discount should be greater than 0 when IsDiscounted is tru
e.");
}
}

In this case, the When method is used to apply the validation rule only when the Discount property is greater than
0.

5. Validate Nested Complex or Collection Property using Fluent API


FluentValidation supports the validation of nested complex properties (i.e., models that contain other models) and
collections (lists, arrays, etc.).
Nested Model Validation Example:
If you have a Product model with a nested Category model, you can validate the Category properties within
the ProductValidator .
public class Category csharp
{
public string Name { get; set; }
}

public class Product


{
public string Name { get; set; }
public Category Category { get; set; }
}

public class ProductValidator : AbstractValidator<Product>


{
public ProductValidator()
{
RuleFor(x => x.Name).NotEmpty();

RuleFor(x => x.Category)


.NotNull().WithMessage("Category is required.")
.SetValidator(new CategoryValidator());
}
}

public class CategoryValidator : AbstractValidator<Category>


{
public CategoryValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Category name is required.");
}
}

In this case, the CategoryValidator is applied to the Category property of the Product model.
FluentValidation will recursively validate nested models.
Collection Validation Example:
You can also validate collections (arrays, lists) of models.
public class Order csharp
{
public List<Product> Products { get; set; }
}

public class OrderValidator : AbstractValidator<Order>


{
public OrderValidator()
{
RuleForEach(x => x.Products).SetValidator(new ProductValidator());
}
}

This validator ensures that every product in the Products list is validated according to the ProductValidator .

Summary:
Fluent API Validation: Enables you to define complex and flexible validation rules in a fluent and readable
manner.
Async Validators: Support asynchronous validation for scenarios involving external data sources.
Custom Validators: Allows you to create custom validation logic using the Custom method.
Conditional Validations: FluentValidation supports conditional validation based on the state of other properties
or conditions.
Nested and Collection Validations: FluentValidation can validate nested models and collections, ensuring that
all parts of complex structures are validated.
By using FluentValidation, you can create clean, maintainable, and reusable validation rules in your ASP.NET Core Web
API applications.
Filters in ASP.NET Core Web API
In ASP.NET Core Web API, filters are a mechanism that allows developers to run code before or after an action
method runs. Filters are commonly used to handle cross-cutting concerns such as logging, error handling,
authentication, authorization, caching, and more.
ASP.NET Core provides different types of filters which can be applied globally, at the controller level, or at the action
level. Filters can be categorized into the following types:
1. Authorization Filters – Run before any other filter, used for checking if the user is authorized to execute the
action.
2. Resource Filters – Run after the authorization filter but before model binding and action execution.
3. Action Filters – Run before and after an action method executes, ideal for logic that needs to be executed
before or after a specific action.
4. Exception Filters – Handle exceptions thrown during the execution of a request.
5. Result Filters – Run before and after the action result is executed, used for modifying the response before it is
returned to the client.
In this article, we will specifically focus on Authorization Filters and Resource Filters.

1. Authorization Filters in ASP.NET Core Web API


Authorization Filters are the first filters to execute in the pipeline. They run before any other filters and are
responsible for checking whether a user is authorized to access a given resource or action. If the user is not
authorized, the action is prevented from running.
How Authorization Filters Work:
Authorization filters execute before any other filter type in the filter pipeline.
They are used to check whether a user is authenticated and authorized to execute a given action.
Typically, they are used for authentication and authorization logic.
Custom Authorization Filter Example:
Here’s how you can create a custom Authorization Filter:
1. Create the Authorization Filter:
public class CustomAuthorizationFilter : IAuthorizationFilter csharp
{
public void OnAuthorization(AuthorizationFilterContext context)
{
// Check if the user is authenticated
var isAuthenticated = context.HttpContext.User.Identity.IsAuthenticated;

if (!isAuthenticated)
{
// Return an Unauthorized response if not authenticated
context.Result = new UnauthorizedResult();
}
}
}

2. Register the Authorization Filter:


You can register the filter globally in Startup.cs or use it at the controller or action level.
Global registration:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddControllers(options =>
{
options.Filters.Add<CustomAuthorizationFilter>();
});
}

Controller-level registration:
[ServiceFilter(typeof(CustomAuthorizationFilter))] csharp
public class MyController : ControllerBase
{
public IActionResult Get()
{
return Ok("Authorized");
}
}

Action-level registration:
[HttpGet] csharp
[ServiceFilter(typeof(CustomAuthorizationFilter))]
public IActionResult GetData()
{
return Ok("Authorized");
}

In the example above, the CustomAuthorizationFilter checks whether the user is authenticated. If the user is
not authenticated, an UnauthorizedResult is returned.

2. Resource Filters in ASP.NET Core Web API


Resource Filters are the second type of filter in the ASP.NET Core filter pipeline. They run after the authorization filter
but before the action method executes. Resource filters are primarily used for operations that deal with request data,
such as resource caching, or pre-processing data before the action executes.
Resource filters are a great way to implement functionality that needs to be applied to all or most of the action
methods in a controller, such as:
Caching responses or data.
Pre-processing request data before the action method runs.
Managing resource allocation (like database connections).
How Resource Filters Work:
Resource Filters run before model binding and before the action method executes.
They are typically used for preprocessing logic that is common to multiple action methods (e.g., caching,
logging, or transforming request data).
The OnResourceExecuting method runs before the action method, while OnResourceExecuted runs after.
Custom Resource Filter Example:
1. Create the Resource Filter:
Here’s an example of a custom Resource Filter that logs the start and end time of a request.
public class CustomResourceFilter : IResourceFilter csharp
{
private readonly ILogger<CustomResourceFilter> _logger;

public CustomResourceFilter(ILogger<CustomResourceFilter> logger)


{
_logger = logger;
}

// Called before the action method is executed.


public void OnResourceExecuting(ResourceExecutingContext context)
{
_logger.LogInformation("Request started at: {0}", DateTime.UtcNow);
}

// Called after the action method is executed.


public void OnResourceExecuted(ResourceExecutedContext context)
{
_logger.LogInformation("Request ended at: {0}", DateTime.UtcNow);
}
}

2. Register the Resource Filter:


You can apply the Resource Filter globally, at the controller level, or at the action level.
Global Registration:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddControllers(options =>
{
options.Filters.Add<CustomResourceFilter>();
});
}

Controller-level Registration:
[ServiceFilter(typeof(CustomResourceFilter))] csharp
public class MyController : ControllerBase
{
public IActionResult Get()
{
return Ok("Resource Filter Applied");
}
}

Action-level Registration:
[HttpGet] csharp
[ServiceFilter(typeof(CustomResourceFilter))]
public IActionResult GetData()
{
return Ok("Resource Filter Applied");
}

In this example, the logs the start and end time of a request. The
CustomResourceFilter
OnResourceExecuting method is executed before the action method, and OnResourceExecuted is executed
after the action method completes.

Filter Execution Order in ASP.NET Core Web API


The order in which filters are executed is as follows:
1. Authorization Filters – Run first. They are used for checking whether the user is authorized to execute the
action.
2. Resource Filters – Run after authorization filters, but before model binding.
3. Action Filters – Run before and after the action method executes.
4. Exception Filters – Handle exceptions thrown during the execution of an action.
5. Result Filters – Run before and after the action result is executed, used to modify the response.

Conclusion
Authorization Filters: Used to ensure that a user is authorized to perform a certain action. They are typically
used to handle authentication and authorization logic.
Resource Filters: Used for actions that need to execute before model binding and action execution. They are
ideal for tasks like caching or pre-processing data.
These filters allow for a modular, reusable, and maintainable way to add cross-cutting concerns such as security,
logging, and caching in an ASP.NET Core Web API application. They can be applied globally or at the controller or
action level, depending on the specific needs of the application.
Security and Authentication in ASP.NET Core Web API
Security is one of the most important concerns when developing web APIs. ASP.NET Core provides various
mechanisms for securing and authenticating API requests, including password hashing, token-based authentication
(JWT), and encryption. Below, we cover several key concepts and implementations related to security and
authentication in ASP.NET Core Web API.

1. How to Store Password in Hash Format in ASP.NET Core Web API


Storing passwords in plaintext is a major security risk. Therefore, it is important to store passwords in a hashed
format. ASP.NET Core provides built-in tools to hash passwords securely using the PasswordHasher class.
Implementation:
1. Hash Password Example:
using Microsoft.AspNetCore.Identity; csharp

public class UserService


{
private readonly PasswordHasher<ApplicationUser> _passwordHasher;

public UserService()
{
_passwordHasher = new PasswordHasher<ApplicationUser>();
}

public string HashPassword(string password)


{
var hashedPassword = _passwordHasher.HashPassword(null, password);
return hashedPassword;
}

public bool VerifyPassword(string hashedPassword, string passwordToVerify)


{
var result = _passwordHasher.VerifyHashedPassword(null, hashedPassword, pas
swordToVerify);
return result == PasswordVerificationResult.Success;
}
}

2. Storing the hashed password in a database (e.g., SQL Server) will ensure that passwords are never stored in
plaintext.
Why Use Password Hashing?
Security: Even if the database is compromised, attackers won’t have access to users' actual passwords.
Compliance: Hashing passwords helps meet various compliance standards (e.g., GDPR, PCI DSS).
2. HMAC Authentication in ASP.NET Core Web API
HMAC (Hash-based Message Authentication Code) is used for ensuring the integrity and authenticity of a
message. It's commonly used for secure API communication.
HMAC Implementation Example:
1. Generate HMAC Hash:
using System.Security.Cryptography; csharp
using System.Text;

public class HMACService


{
public string GenerateHmacHash(string message, string secretKey)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey)))
{
byte[] hashMessage = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToBase64String(hashMessage);
}
}
}

2. Verify HMAC Hash: The server can verify the hash by recalculating it using the same secret key and comparing
it to the sent hash.

3. Encryption and Decryption in ASP.NET Core Web API


Encryption ensures that data is securely transmitted, and only authorized parties can read it. ASP.NET Core supports
both symmetric and asymmetric encryption algorithms.
Symmetric Encryption Example (AES):
1. Encrypt Data using AES:
using System.IO; csharp
using System.Security.Cryptography;
using System.Text;

public class EncryptionService


{
public string EncryptData(string data, string key)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Encoding.UTF8.GetBytes(key); // 16-byte key
aesAlg.IV = new byte[16]; // Initialization vector (can be random for
each encryption)

ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.


IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encrypt
or, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(data);
}
}
return Convert.ToBase64String(msEncrypt.ToArray());
}
}
}
}

2. Decrypt Data:
public string DecryptData(string encryptedData, string key) csharp
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Encoding.UTF8.GetBytes(key);
aesAlg.IV = new byte[16]; // Assuming the IV used for encryption is 16 byt
es.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(e


ncryptedData)))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor,
CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
}

4. Asymmetric Encryption in ASP.NET Core Web API


Asymmetric Encryption uses two keys: a public key (to encrypt data) and a private key (to decrypt data). It's
commonly used in digital signatures and public-key cryptography.
RSA Encryption Example:
1. Encrypt Data using RSA Public Key:
using System.Security.Cryptography; csharp
using System.Text;

public class RsaService


{
private RSACryptoServiceProvider _rsa;

public RsaService()
{
_rsa = new RSACryptoServiceProvider();
}

public string EncryptData(string data, string publicKey)


{
_rsa.FromXmlString(publicKey);
byte[] byteData = Encoding.UTF8.GetBytes(data);
byte[] encryptedData = _rsa.Encrypt(byteData, false);
return Convert.ToBase64String(encryptedData);
}
}

2. Decrypt Data using RSA Private Key:


public string DecryptData(string encryptedData, string privateKey) csharp
{
_rsa.FromXmlString(privateKey);
byte[] byteEncryptedData = Convert.FromBase64String(encryptedData);
byte[] decryptedData = _rsa.Decrypt(byteEncryptedData, false);
return Encoding.UTF8.GetString(decryptedData);
}

5. Basic Authentication in ASP.NET Core Web API


Basic Authentication sends the username and password as a base64-encoded string in the HTTP request header.
It’s considered less secure unless combined with HTTPS.
Basic Authentication Example:
1. Add Basic Authentication Middleware:
public class BasicAuthMiddleware csharp
{
private readonly RequestDelegate _next;
public BasicAuthMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)


{
var authorization = context.Request.Headers["Authorization"];

if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Basi


c"))
{
var encodedCredentials = authorization.Substring("Basic ".Length).Trim
();
var decodedCredentials = Encoding.UTF8.GetString(Convert.FromBase64Stri
ng(encodedCredentials));
var credentials = decodedCredentials.Split(':');

var username = credentials[0];


var password = credentials[1];

// Validate credentials here


if (username != "admin" || password != "password")
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Invalid credentials");
return;
}
}
await _next(context);
}
}

2. Register Middleware:
public void Configure(IApplicationBuilder app) csharp
{
app.UseMiddleware<BasicAuthMiddleware>();
}

6. JWT Authentication in ASP.NET Core Web API


JWT (JSON Web Token) is a token-based authentication method that provides secure communication between a
client and server. It’s commonly used for user authentication and authorization.
JWT Authentication Example:
1. Create JWT Token:
public class JwtService csharp
{
private readonly string _secretKey;

public JwtService(IConfiguration config)


{
_secretKey = config["Jwt:SecretKey"];
}

public string GenerateToken(string username)


{
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, "Admin")
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));


var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(


issuer: "yourdomain.com",
audience: "yourdomain.com",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);

return new JwtSecurityTokenHandler().WriteToken(token);


}
}

2. Authenticate with JWT:


Use JWT token in the Authorization header in subsequent API requests.

7. Refresh Token in ASP.NET Core Web API using JWT Authentication


A Refresh Token is used to obtain a new access token when the current access token expires.
Refresh Token Example:
1. Generate Refresh Token:
public class RefreshTokenService csharp
{
public string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}
}

2. Refresh JWT Token: When the access token expires, the client can use the refresh token to get a new one.

8. Role-Based JWT Authentication in ASP.NET Core Web API


Role-based Authentication allows users to have roles (e.g., Admin, User) and restrict access to certain resources
based on these roles.
Role-Based JWT Example:
1. Assign Roles in Claims:
var claims = new[] csharp
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, "Admin") // User's role
};

2. Authorize Based on Roles:


[Authorize(Roles = "Admin")] csharp
public IActionResult GetAdminData()
{
return Ok("Admin data");
}

9. CORS in ASP.NET Core Web API


CORS (Cross-Origin Resource Sharing) is a mechanism that allows web applications from one domain to make
requests to an API hosted on another domain.
Enable CORS in ASP.NET Core:
1. Configure CORS in Startup.cs:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
}

public void Configure(IApplicationBuilder app)


{
app.UseCors("AllowAll"); // Apply CORS policy
}

These security practices, including password hashing, HMAC, encryption, JWT authentication, and CORS, help to
secure the data, authentication, and access to your ASP.NET Core Web API endpoints, ensuring that your application
is secure and follows modern security best practices.
SSO Authentication in ASP.NET Core Web API
SSO (Single Sign-On) Authentication enables users to authenticate once and gain access to multiple applications
without having to sign in again. It is commonly used in organizations to simplify the user experience and centralize
authentication. In an SSO system, a central Identity Provider (IdP) authenticates the user, and other applications
(called Service Providers) trust the IdP to validate the user and authorize their access.
In ASP.NET Core Web API, SSO Authentication is typically implemented using OpenID Connect (OIDC) and OAuth
2.0. These protocols allow a user to authenticate with a central authority (e.g., an identity provider like Azure AD,
IdentityServer, or Okta), and access multiple APIs without needing to log in separately.
Steps to Implement SSO Authentication in ASP.NET Core Web API:
1. Install NuGet Packages: You'll need to install the required packages for OpenID Connect and JWT
authentication:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect bash
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

2. Configure Authentication in Startup.cs or Program.cs :


In ConfigureServices , add authentication configuration using OpenID Connect for your Web API:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationSchem
e;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://identityprovider.com"; // Identity Provider's
URL
options.ClientId = "your-client-id";
options.ClientSecret = "your-client-secret";
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
});

services.AddControllers();
}

3. Use Authentication Middleware: Add authentication and authorization middleware in the Configure method
of Startup.cs :
public void Configure(IApplicationBuilder app) csharp
{
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

4. Access User Information: To get user details after successful authentication:


[Authorize] csharp
[HttpGet("userinfo")]
public IActionResult GetUserInfo()
{
var userName = User.Identity.Name;
return Ok(new { UserName = userName });
}

Authentication Server using ASP.NET Core Web API


An Authentication Server (often called Identity Provider) is responsible for authenticating the user, issuing tokens
(JWT, ID tokens), and providing them to the requesting client applications. The Authentication Server typically uses
OAuth 2.0 or OpenID Connect protocols for issuing and validating tokens.
Steps to Implement Authentication Server:
1. Create an Identity Server using IdentityServer4 or another framework like OpenIddict:
Install IdentityServer package:
dotnet add package IdentityServer4 bash

2. Configure IdentityServer in Startup.cs :


Configure clients, API resources, and identity resources:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddDeveloperSigningCredential();
}

Define the Config class that contains your clients, API scopes, and identity resources:
public static class Config csharp
{
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientId = "mvc_client",
AllowedGrantTypes = GrantTypes.Code,
ClientSecrets = { new Secret("secret".Sha256()) },
RedirectUris = { "https://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback
-oidc" },
AllowedScopes = { "openid", "profile", "api1" }
}
};

public static IEnumerable<ApiScope> ApiScopes =>


new ApiScope[]
{
new ApiScope("api1", "My API")
};

public static IEnumerable<IdentityResource> IdentityResources =>


new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
3. Run IdentityServer: When you run your Authentication Server (Identity Provider), it will handle user
authentication and issue access tokens for client applications.

Resource Server using ASP.NET Core Web API


A Resource Server is where your APIs are hosted. It is responsible for validating the access token sent by clients and
granting access to the resources (data, services) if the token is valid.
Steps to Implement Resource Server:
1. Configure JWT Bearer Authentication: In your resource server, configure JWT authentication to validate
incoming tokens.
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://identityprovider.com"; // The Identity Pr
ovider's URL
options.Audience = "api1"; // API's unique identifier (e.g., "api1")
options.RequireHttpsMetadata = false;
});
services.AddAuthorization();
services.AddControllers();
}

2. Protect Endpoints with Authorization: Use the [Authorize] attribute to protect API endpoints:
[Authorize] csharp
[HttpGet("secure-data")]
public IActionResult GetSecureData()
{
return Ok(new { Data = "This is protected data" });
}

3. Validate the Token: The API will validate the incoming JWT token automatically based on the configuration. Only
valid tokens will allow access to the secured resources.

Client Application One using ASP.NET Core MVC


The Client Application is the application that interacts with the Authentication Server and consumes resources from
the Resource Server using the token issued after authentication.
Steps to Implement Client Application One:
1. Install Authentication Packages: Install the necessary packages for OpenID Connect authentication in the MVC
application:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect bash

2. Configure OpenID Connect Authentication in Startup.cs or Program.cs :


public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationSchem
e;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://identityprovider.com"; // Identity Provider's
URL
options.ClientId = "mvc_client";
options.ClientSecret = "secret";
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
});
}

3. Authorization in MVC:
Protect the controller actions that require authentication by using the [Authorize] attribute:
[Authorize] csharp
public IActionResult SecurePage()
{
return View();
}

Client Application Two using ASP.NET Core MVC


Client Application Two behaves in the same way as Client Application One. It interacts with the same Identity
Provider for SSO authentication and uses the access token to access resources from the Resource Server.
Steps for Client Application Two:
1. Use Same Authentication Configuration:
In Startup.cs , configure OpenID Connect for Client Application Two just as done in Client Application One:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationSchem
e;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://identityprovider.com";
options.ClientId = "mvc_client_two";
options.ClientSecret = "secret";
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
});
}

2. Secure Endpoints:
As with Client Application One, use the [Authorize] attribute to secure the routes in Client Application
Two:
[Authorize] csharp
public IActionResult Dashboard()
{
return View();
}

Conclusion
SSO Authentication allows users to authenticate once with a central identity provider and access multiple
applications or APIs without needing to log in separately.
The Authentication Server (Identity Provider) issues tokens and manages user authentication.
The Resource Server validates tokens and serves data or services to authenticated clients.
Client Applications (ASP.NET Core MVC) interact with the Authentication Server to authenticate users and
consume resources from the Resource Server.
By setting up a robust SSO system, you can streamline user authentication, increase security, and improve user
experience across multiple web applications and APIs.
ASP.NET Core Web API Versioning
API Versioning is an important concept when it comes to managing different versions of your API. It allows you to
introduce new features and changes to the API without breaking existing clients. ASP.NET Core provides several ways
to handle versioning to support backward compatibility.
There are multiple approaches to versioning an API in ASP.NET Core Web API. Some common strategies include:
1. Query String Versioning: The version is passed as a parameter in the query string.
2. URL Path Versioning: The version is included directly in the URL path.
3. Header Versioning: The version is specified in the request header.
4. Media Type Versioning: The version is specified using the "Accept" header in the request, commonly using
MIME types.
ASP.NET Core Web API Versioning
To implement versioning in your API, you need to use the Microsoft.AspNetCore.Mvc.Versioning package. This
package provides a simple and flexible way to manage versions for your Web API.
1. Install NuGet Package for Versioning:
dotnet add package Microsoft.AspNetCore.Mvc.Versioning bash

2. Configure API Versioning in Startup.cs :


Add the versioning services in ConfigureServices :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ApiVersionReader = ApiVersionReader.Combine(
new QueryStringApiVersionReader("api-version"),
new HeaderApiVersionReader("X-API-Version"),
new UrlSegmentApiVersionReader());
});

services.AddControllers();
}

This configuration sets up the versioning system for query strings, headers, and URL paths.

ASP.NET Core Web API Versioning using Query String


In Query String Versioning, the API version is passed as a parameter in the query string of the request URL.
Steps to Implement Query String Versioning:
1. Configure Query String Versioning in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddApiVersioning(options =>
{
options.ApiVersionReader = new QueryStringApiVersionReader("api-version");
});

services.AddControllers();
}

2. Controller Example with Versioning:


In the controller, use the ApiVersion attribute to specify which version of the API this controller is handling:
[ApiVersion("1.0")] csharp
[Route("api/v{version:apiVersion}/products")]
[ApiController]
public class ProductsV1Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 1");
}
}

[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
[ApiController]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 2");
}
}

3. Example Request: To request version 1.0, use:


GET /api/products?api-version=1.0

To request version 2.0, use:


GET /api/products?api-version=2.0
ASP.NET Core Web API Versioning using URL Path
In URL Path Versioning, the version is included directly in the URL of the request. This is one of the most common
and simple approaches.
Steps to Implement URL Path Versioning:
1. Configure URL Path Versioning in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddApiVersioning(options =>
{
options.ApiVersionReader = new UrlSegmentApiVersionReader();
});

services.AddControllers();
}

2. Controller Example with Versioning:


The controller will have versions defined in the route using the {version:apiVersion} parameter:
[ApiVersion("1.0")] csharp
[Route("api/v{version:apiVersion}/products")]
[ApiController]
public class ProductsV1Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 1");
}
}

[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
[ApiController]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 2");
}
}

3. Example Request: To access version 1.0, use the URL:


GET /api/v1/products

To access version 2.0, use the URL:


GET /api/v2/products

Header Versioning in ASP.NET Core Web API


In Header Versioning, the version of the API is specified in the request header. This approach is useful when you
don't want the client to modify the URL or query string.
Steps to Implement Header Versioning:
1. Configure Header Versioning in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddApiVersioning(options =>
{
options.ApiVersionReader = new HeaderApiVersionReader("X-API-Version");
});

services.AddControllers();
}

2. Controller Example with Versioning:


The controller should remain the same as in the previous examples, and the version is automatically picked up
from the request header.
[ApiVersion("1.0")] csharp
[Route("api/products")]
[ApiController]
public class ProductsV1Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 1");
}
}

[ApiVersion("2.0")]
[Route("api/products")]
[ApiController]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 2");
}
}

3. Example Request:
To access version 1.0, include the following header:
GET /api/products
X-API-Version: 1.0

To access version 2.0, include the following header:


GET /api/products
X-API-Version: 2.0

Media Type Versioning in ASP.NET Core Web API


In Media Type Versioning, the version is specified in the Accept header of the request. This versioning strategy is
typically used with Content Negotiation, allowing the client to request a specific version by specifying it in the media
type.
Steps to Implement Media Type Versioning:
1. Configure Media Type Versioning in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddApiVersioning(options =>
{
options.ApiVersionReader = new MediaTypeApiVersionReader("v");
});

services.AddControllers();
}

2. Controller Example with Versioning:


The controller will handle the version specified in the media type of the request:
[ApiVersion("1.0")] csharp
[Route("api/products")]
[ApiController]
public class ProductsV1Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 1");
}
}

[ApiVersion("2.0")]
[Route("api/products")]
[ApiController]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products API Version 2");
}
}

3. Example Request:
To access version 1.0, set the Accept header as:
GET /api/products
Accept: application/vnd.myapi.v1+json

To access version 2.0, set the Accept header as:


GET /api/products
Accept: application/vnd.myapi.v2+json

Conclusion
Query String Versioning: The version is passed as a query string parameter (e.g., ?api-version=1.0 ).
URL Path Versioning: The version is included as part of the URL path (e.g., /api/v1/products ).
Header Versioning: The version is specified in the request header (e.g., X-API-Version: 1.0 ).
Media Type Versioning: The version is specified in the Accept header (e.g.,
application/vnd.myapi.v1+json ).

These versioning strategies provide flexibility in how your API exposes different versions to clients, helping you
maintain backward compatibility while evolving your API.
E-Commerce Real-Time Application Development using ASP.NET Core Web API
Developing an E-Commerce application using ASP.NET Core Web API requires building a system that handles
products, orders, users, payment gateways, and various business logic. This guide walks through the steps to build a
simple E-Commerce platform with real-time features using ASP.NET Core Web API.
Key Features of an E-Commerce API
1. User Management: Authentication, Authorization, and User Profile.
2. Product Management: Add, Edit, Delete Products, and retrieve product information.
3. Cart Management: Add products to the shopping cart, view, and update cart items.
4. Order Management: Create, view, and update orders, including processing payments.
5. Payment Gateway Integration: Handle payment processes (mock or actual).
6. Real-Time Notifications: Notify users when their order is confirmed or when there are updates (using SignalR or
another method).
Steps to Build E-Commerce Application with ASP.NET Core Web API
1. Set Up Project
1. Create a New ASP.NET Core Web API Project: You can create a new project using Visual Studio or CLI.
dotnet new webapi -n ECommerceApp bash
cd ECommerceApp

2. Install Required NuGet Packages:


AutoMapper for object-to-object mapping.
Swagger for API documentation.
Entity Framework Core for data access.
JWT Authentication for secure API access.
SignalR for real-time notifications (optional).
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection bash
dotnet add package Swashbuckle.AspNetCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.AspNetCore.SignalR

2. Database Design
A basic E-Commerce system may have the following entities:
User: Users can register, log in, and manage their profiles.
Product: Store products available for purchase.
Cart: Store products added by users before checkout.
Order: Store orders once the user completes a purchase.
Payment: Handle payment transactions.
Entities:
User Entity:
public class User csharp
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string Role { get; set; }
}

Product Entity:
public class Product csharp
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockQuantity { get; set; }
}

Order Entity:
public class Order csharp
{
public int Id { get; set; }
public int UserId { get; set; }
public DateTime OrderDate { get; set; }
public string Status { get; set; } // "Pending", "Confirmed", "Shipped", "Deliv
ered"
public decimal TotalAmount { get; set; }
public List<OrderItem> OrderItems { get; set; }
}

public class OrderItem


{
public int ProductId { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}

3. Database Context (DbContext)


public class ECommerceDbContext : DbContext csharp
{
public DbSet<User> Users { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Order> Orders { get; set; }

public ECommerceDbContext(DbContextOptions<ECommerceDbContext> options)


: base(options) { }
}

4. Add Authentication with JWT


Set up JWT Authentication to secure the API endpoints.
Configure JWT Authentication in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = "your_issuer",
ValidAudience = "your_audience",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBy
tes("your_secret_key"))
};
});

services.AddControllers();
services.AddDbContext<ECommerceDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnectio
n")));
services.AddSwaggerGen();
}

Generate JWT Token on login:


public class AuthController : ControllerBase csharp
{
private readonly ECommerceDbContext _context;

public AuthController(ECommerceDbContext context)


{
_context = context;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{
var user = _context.Users.FirstOrDefault(u => u.Email == model.Email);
if (user == null || !VerifyPassword(model.Password, user.PasswordHash))
return Unauthorized();

var token = GenerateJwtToken(user);


return Ok(new { Token = token });
}

private string GenerateJwtToken(User user)


{
var claims = new[] {
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Role)
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_ke


y"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(


issuer: "your_issuer",
audience: "your_audience",
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);

return new JwtSecurityTokenHandler().WriteToken(token);


}
}

5. Product and Cart Management API


Create API endpoints for managing products and cart actions.
Product Controller:
[ApiController] csharp
[Route("api/products")]
public class ProductsController : ControllerBase
{
private readonly ECommerceDbContext _context;

public ProductsController(ECommerceDbContext context)


{
_context = context;
}
[HttpGet]
public IActionResult GetProducts()
{
var products = _context.Products.ToList();
return Ok(products);
}

[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
_context.Products.Add(product);
_context.SaveChanges();
return CreatedAtAction(nameof(GetProducts), new { id = product.Id }, produc
t);
}
}

Cart Controller:
[ApiController] csharp
[Route("api/cart")]
public class CartController : ControllerBase
{
private readonly ECommerceDbContext _context;

public CartController(ECommerceDbContext context)


{
_context = context;
}

[HttpGet]
public IActionResult GetCartItems(int userId)
{
var cartItems = _context.CartItems.Where(c => c.UserId == userId).ToList();
return Ok(cartItems);
}

[HttpPost]
public IActionResult AddToCart([FromBody] CartItem item)
{
_context.CartItems.Add(item);
_context.SaveChanges();
return Ok(item);
}
}

6. Order Management API


Create endpoints for order management, including order creation and processing.
Order Controller:
[ApiController] csharp
[Route("api/orders")]
public class OrdersController : ControllerBase
{
private readonly ECommerceDbContext _context;

public OrdersController(ECommerceDbContext context)


{
_context = context;
}

[HttpPost]
public IActionResult PlaceOrder([FromBody] Order order)
{
_context.Orders.Add(order);
_context.SaveChanges();
return Ok(order);
}

[HttpGet("{id}")]
public IActionResult GetOrder(int id)
{
var order = _context.Orders.Include(o => o.OrderItems).FirstOrDefault(o =>
o.Id == id);
if (order == null)
return NotFound();

return Ok(order);
}
}

7. Real-Time Notifications Using SignalR


SignalR can be used for real-time notifications, such as notifying the user when their order is confirmed or shipped.
Install SignalR:
dotnet add package Microsoft.AspNetCore.SignalR bash

Create SignalR Hub:


public class NotificationHub : Hub csharp
{
public async Task SendOrderStatusUpdate(string user, string message)
{
await Clients.User(user).SendAsync("ReceiveMessage", message);
}
}
Configure SignalR in Startup.cs :
public void ConfigureServices csharp

Hotel Booking Application using ASP.NET Core Web API


A Hotel Booking Application allows users to search for hotels, book rooms, manage their bookings, and cancel
reservations. It involves several modules, including user management, room and hotel management, booking, and
cancellation. Here's how you can implement a real-time Hotel Booking Application using ASP.NET Core Web API.

Modules in Hotel Booking Application


1. User Module: Manages user registration, authentication, and profile management.
2. Room Type Module: Defines different room categories (e.g., single, double, suite).
3. Room Module: Manages rooms associated with hotels.
4. Amenities Module: Defines the facilities available (e.g., Wi-Fi, breakfast, pool).
5. Room Amenities Module: Links rooms to amenities.
6. Hotel Search Module: Allows users to search for hotels based on location, price, and availability.
7. Hotel Booking Module: Allows users to book a room.
8. Hotel Cancellation Module: Allows users to cancel a booking.

1. Database Design of Hotel Booking Application


A relational database is required to manage entities such as Users, Rooms, Bookings, Hotels, and Amenities. Below
are the database entities.
Entities
User:
public class User csharp
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string Role { get; set; } // "Admin", "Customer"
}

Hotel:
public class Hotel csharp
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public decimal Rating { get; set; }
}

RoomType:
public class RoomType csharp
{
public int Id { get; set; }
public string Name { get; set; } // "Single", "Double", "Suite"
public decimal Price { get; set; }
}

Room:
public class Room csharp
{
public int Id { get; set; }
public int HotelId { get; set; }
public int RoomTypeId { get; set; }
public bool IsAvailable { get; set; }
public decimal Price { get; set; }
public int Capacity { get; set; }
}

Amenity:
public class Amenity csharp
{
public int Id { get; set; }
public string Name { get; set; } // "Wi-Fi", "Breakfast", "Pool"
}

RoomAmenity:
public class RoomAmenity csharp
{
public int RoomId { get; set; }
public int AmenityId { get; set; }
}

Booking:
public class Booking csharp
{
public int Id { get; set; }
public int UserId { get; set; }
public int RoomId { get; set; }
public DateTime CheckInDate { get; set; }
public DateTime CheckOutDate { get; set; }
public string Status { get; set; } // "Confirmed", "Pending", "Cancelled"
}

2. ASP.NET Core Web API Project Setup for Hotel Booking


1. Create a new ASP.NET Core Web API Project: You can create a new project using the .NET CLI or Visual Studio.
dotnet new webapi -n HotelBookingAPI bash
cd HotelBookingAPI

2. Install Necessary NuGet Packages: Install packages for Entity Framework Core and Swagger (for API
documentation).
dotnet add package Microsoft.EntityFrameworkCore.SqlServer bash
dotnet add package Swashbuckle.AspNetCore

3. Configure Database Context: Create HotelBookingDbContext to manage database operations.


public class HotelBookingDbContext : DbContext csharp
{
public DbSet<User> Users { get; set; }
public DbSet<Hotel> Hotels { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<RoomType> RoomTypes { get; set; }
public DbSet<Amenity> Amenities { get; set; }
public DbSet<RoomAmenity> RoomAmenities { get; set; }
public DbSet<Booking> Bookings { get; set; }

public HotelBookingDbContext(DbContextOptions<HotelBookingDbContext> options)


: base(options)
{ }
}

4. Add Database Connection String: In appsettings.json , add the connection string.


"ConnectionStrings": { json
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HotelBookingDB;Trus
ted_Connection=True;"
}

3. User Module of Hotel Booking Application


User Registration and Authentication: Implement user registration and login using JWT Authentication.
[ApiController] csharp
[Route("api/users")]
public class UsersController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public UsersController(HotelBookingDbContext context)


{
_context = context;
}

[HttpPost("register")]
public IActionResult Register([FromBody] RegisterModel model)
{
// Implement user registration logic here
// Hash password, save user, etc.
return Ok();
}

[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{
// Implement login logic and return JWT token
return Ok(new { Token = "your_generated_token" });
}
}

4. Room Type Module of Hotel Booking Application


Add Room Types: Define different room categories in the system.
[ApiController] csharp
[Route("api/roomtypes")]
public class RoomTypesController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public RoomTypesController(HotelBookingDbContext context)


{
_context = context;
}

[HttpGet]
public IActionResult GetRoomTypes()
{
var roomTypes = _context.RoomTypes.ToList();
return Ok(roomTypes);
}
}

5. Room Module of Hotel Booking Application


Manage Room Availability: Define rooms and their availability.
[ApiController] csharp
[Route("api/rooms")]
public class RoomsController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public RoomsController(HotelBookingDbContext context)


{
_context = context;
}

[HttpGet]
public IActionResult GetRooms(int hotelId)
{
var rooms = _context.Rooms.Where(r => r.HotelId == hotelId).ToList();
return Ok(rooms);
}
}

6. Amenities Module of Hotel Booking Application


Manage Amenities: Create and retrieve amenities available at hotels.
[ApiController] csharp
[Route("api/amenities")]
public class AmenitiesController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public AmenitiesController(HotelBookingDbContext context)


{
_context = context;
}

[HttpGet]
public IActionResult GetAmenities()
{
var amenities = _context.Amenities.ToList();
return Ok(amenities);
}
}

7. Hotel Search Module of Hotel Booking Application


Search for Hotels: Allow users to search hotels by location and other filters.
[ApiController] csharp
[Route("api/hotels")]
public class HotelsController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public HotelsController(HotelBookingDbContext context)


{
_context = context;
}
[HttpGet]
public IActionResult SearchHotels(string location, decimal? minPrice, decimal?
maxPrice)
{
var hotels = _context.Hotels.Where(h => h.Location.Contains(location)).ToLi
st();
// Apply additional filters for price
return Ok(hotels);
}
}

8. Implementing Hotel Booking Module


Booking a Room: Users can book a room by selecting a room, specifying check-in/check-out dates.
[ApiController] csharp
[Route("api/bookings")]
public class BookingsController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public BookingsController(HotelBookingDbContext context)


{
_context = context;
}

[HttpPost]
public IActionResult BookRoom([FromBody] BookingModel model)
{
var booking = new Booking
{
UserId = model.UserId,
RoomId = model.RoomId

, CheckInDate = model.CheckInDate, CheckOutDate = model.CheckOutDate, Status = "Pending" };


context.Bookings.Add(booking); context.SaveChanges(); return Ok(booking); } }

---

### **9. Implementing the Hotel Cancellation Module**

- **Cancel a Booking**:
Users can cancel their existing booking.

```csharp
[ApiController]
[Route("api/cancellations")]
public class CancellationsController : ControllerBase
{
private readonly HotelBookingDbContext _context;

public CancellationsController(HotelBookingDbContext context)


{
_context = context;
}

[HttpPost]
public IActionResult CancelBooking([FromBody] CancellationModel model)
{
var booking = _context.Bookings.FirstOrDefault(b => b.Id == model.BookingId &&
b.UserId == model.UserId);
if (booking == null || booking.Status == "Cancelled")
return BadRequest("Booking cannot be cancelled.");

booking.Status = "Cancelled";
_context.SaveChanges();
return Ok(booking);
}
}

Conclusion
By following the above modules and steps, you can create a complete Hotel Booking System using ASP.NET Core
Web API. This application can be expanded to include features like payment integration, reviews, discounts, and
user notifications using tools like SignalR. Each module can be independently scaled, and the application
architecture will support a real-time hotel booking solution.
Introduction to Unit Testing in ASP.NET Core
Unit testing is an essential practice in software development that allows you to verify the behavior of individual units of
code (such as methods or functions). In ASP.NET Core, unit testing is crucial for ensuring that your Web API behaves
as expected under different conditions, without requiring a real server or database.
Unit tests focus on testing a small, isolated part of the application, typically a method or a service, ensuring that it
produces the expected results.
In ASP.NET Core, you can perform unit testing using various testing frameworks, such as xUnit, NUnit, and MSTest.
xUnit is one of the most popular frameworks in the .NET ecosystem due to its simplicity, extensibility, and good
integration with ASP.NET Core.
Unit Testing in ASP.NET Core Web API using xUnit Framework
1. Create a Unit Test Project: First, create a unit test project in the same solution as your ASP.NET Core Web API
project. In Visual Studio, you can add a new xUnit Test Project.
Using the .NET CLI:
dotnet new xunit -n MyApi.Tests bash
cd MyApi.Tests
dotnet add reference ../MyApi/MyApi.csproj

2. Install Necessary NuGet Packages: Install xUnit, Moq (for mocking dependencies), and
Microsoft.AspNetCore.Mvc.Testing for integration tests.
dotnet add package xunit bash
dotnet add package Moq
dotnet add package Microsoft.AspNetCore.Mvc.Testing
dotnet add package FluentAssertions

3. Basic Unit Test for a Controller Action: Let's say you have a BookingsController in your Web API that has
a method GetBookingById . You want to write a unit test for that method.
Controller (BookingsController.cs):
[ApiController] csharp
[Route("api/[controller]")]
public class BookingsController : ControllerBase
{
private readonly IBookingService _bookingService;

public BookingsController(IBookingService bookingService)


{
_bookingService = bookingService;
}

[HttpGet("{id}")]
public IActionResult GetBookingById(int id)
{
var booking = _bookingService.GetBookingById(id);
if (booking == null)
return NotFound();
return Ok(booking);
}
}

Unit Test for Controller (BookingsControllerTests.cs):


public class BookingsControllerTests csharp
{
private readonly BookingsController _controller;
private readonly Mock<IBookingService> _mockBookingService;

public BookingsControllerTests()
{
_mockBookingService = new Mock<IBookingService>();
_controller = new BookingsController(_mockBookingService.Object);
}

[Fact]
public void GetBookingById_ReturnsNotFound_WhenBookingDoesNotExist()
{
// Arrange
_mockBookingService.Setup(service => service.GetBookingById(It.IsAny<int>
())).Returns((Booking)null);

// Act
var result = _controller.GetBookingById(1);

// Assert
Assert.IsType<NotFoundResult>(result);
}

[Fact]
public void GetBookingById_ReturnsOk_WhenBookingExists()
{
// Arrange
var booking = new Booking { Id = 1, Name = "Test Booking" };
_mockBookingService.Setup(service => service.GetBookingById(1)).Returns(boo
king);

// Act
var result = _controller.GetBookingById(1);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnBooking = Assert.IsType<Booking>(okResult.Value);
Assert.Equal(1, returnBooking.Id);
}
}

4. Running the Unit Test: You can run the unit tests using Visual Studio Test Explorer or by using the .NET CLI:
dotnet test bash

xUnit Framework Theory Attribute in ASP.NET Core


In xUnit, Theory is an attribute that allows you to run a test method with different sets of data. It helps you test a
method under various conditions and ensures that it works correctly for a range of input values.
1. Using Theory Attribute: The Theory attribute in xUnit allows you to provide parameters for your test method.
It works with InlineData to pass multiple sets of data to a test.
Example:
public class MathTests csharp
{
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, -2, -3)]
[InlineData(10, 20, 30)]
public void AddNumbers_ReturnsCorrectSum(int a, int b, int expected)
{
// Act
var result = a + b;

// Assert
Assert.Equal(expected, result);
}
}

In this example, the test method AddNumbers_ReturnsCorrectSum runs three times with different inputs.

Asynchronous Tests using xUnit Framework in ASP.NET Core


xUnit allows you to write asynchronous tests by making the test method async and returning a Task . This is
particularly useful when you are testing asynchronous code, such as actions in your ASP.NET Core Web API that use
asynchronous database calls or external APIs.
1. Example of Asynchronous Test: Let's say you have an asynchronous method in the controller that returns a list
of bookings from the database.
Controller (BookingsController.cs):
[ApiController] csharp
[Route("api/[controller]")]
public class BookingsController : ControllerBase
{
private readonly IBookingService _bookingService;

public BookingsController(IBookingService bookingService)


{
_bookingService = bookingService;
}

[HttpGet]
public async Task<IActionResult> GetBookings()
{
var bookings = await _bookingService.GetBookingsAsync();
return Ok(bookings);
}
}
Unit Test for Asynchronous Method:
public class BookingsControllerTests csharp
{
private readonly BookingsController _controller;
private readonly Mock<IBookingService> _mockBookingService;

public BookingsControllerTests()
{
_mockBookingService = new Mock<IBookingService>();
_controller = new BookingsController(_mockBookingService.Object);
}

[Fact]
public async Task GetBookings_ReturnsOk_WhenBookingsExist()
{
// Arrange
var bookings = new List<Booking> { new Booking { Id = 1, Name = "Test Booki
ng" } };
_mockBookingService.Setup(service => service.GetBookingsAsync()).ReturnsAsy
nc(bookings);

// Act
var result = await _controller.GetBookings();

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var returnBookings = Assert.IsType<List<Booking>>(okResult.Value);
Assert.Single(returnBookings);
}
}

Notice how GetBookings is an asynchronous method ( Task<IActionResult> ), and the unit test uses
async and await to test the controller action.

Fluent Assertions with xUnit Framework in ASP.NET Core


FluentAssertions is a library that provides a rich set of assertions for writing tests in a more readable and expressive
way. It is especially useful for making assertions that are easy to understand.
1. Install FluentAssertions: First, you need to install the FluentAssertions NuGet package:
dotnet add package FluentAssertions bash

2. Example of Fluent Assertions: Here’s how you can use FluentAssertions to make assertions more fluent in your
unit tests:
public class BookingsControllerTests csharp
{
private readonly BookingsController _controller;
private readonly Mock<IBookingService> _mockBookingService;

public BookingsControllerTests()
{
_mockBookingService = new Mock<IBookingService>();
_controller = new BookingsController(_mockBookingService.Object);
}

[Fact]
public void GetBookingById_ReturnsCorrectBooking_WhenBookingExists()
{
// Arrange
var booking = new Booking { Id = 1, Name = "Test Booking" };
_mockBookingService.Setup(service => service.GetBookingById(1)).Returns(boo
king);

// Act
var result = _controller.GetBookingById(1);

// Assert
var okResult = result.Should().BeOfType<OkObjectResult>().Subject;
var returnBooking = okResult.Value.Should().BeAssignableTo<Booking>().Subje
ct;
returnBooking.Id.Should().Be(1);
returnBooking.Name.Should().Be("Test Booking");
}
}

In this example:
Should().BeOfType<OkObjectResult>() checks the result type.
Should().BeAssignableTo<Booking>() ensures the result is of the correct type.

Fluent assertions make the code more readable and descriptive.

Conclusion
By using xUnit for unit testing in ASP.NET Core Web API, you can ensure that your API is thoroughly tested and
behaves as expected in various scenarios. The ability to write asynchronous tests, use Fluent Assertions, and apply
Theory for parameterized tests allows for efficient,
Minimal API in ASP.NET Core
In ASP.NET Core, Minimal APIs provide a lightweight and simplified way to build HTTP APIs with less boilerplate code.
They allow you to define API routes with minimal setup, using the Program.cs file rather than creating a controller
class.
Minimal APIs are suitable for microservices or small applications where you don't need the overhead of controllers,
and you want to build APIs quickly.
How to Create a Minimal API in ASP.NET Core
1. Create a New ASP.NET Core Project: Using the .NET CLI, create a new web API project:
dotnet new web -n MinimalApiDemo bash
cd MinimalApiDemo

2. Define Endpoints: In Program.cs , you can define minimal API routes directly:
var builder = WebApplication.CreateBuilder(args); csharp
var app = builder.Build();

app.MapGet("/", () => "Hello, World!");


app.MapGet("/greet/{name}", (string name) => $"Hello, {name}!");

app.Run();

3. Run the Application: You can now run the application:


dotnet run bash

This will create a simple API with two endpoints:


GET / – Returns "Hello, World!"

GET /greet/{name} – Returns a greeting with the specified name.

Error Handling and Logging in ASP.NET Core Minimal API


1. Error Handling: In Minimal APIs, you can handle errors using middleware or directly within the endpoint logic.
Here's how you can use a try-catch block for error handling:
app.MapGet("/divide", (int numerator, int denominator) => csharp
{
try
{
if (denominator == 0)
throw new DivideByZeroException("Denominator cannot be zero.");

return Results.Ok(numerator / denominator);


}
catch (DivideByZeroException ex)
{
return Results.BadRequest(ex.Message);
}
});

Alternatively, you can use Exception Middleware for centralized error handling:
app.UseExceptionHandler("/error"); csharp

app.MapGet("/error", () => Results.Problem("An unexpected error occurred."));

2. Logging: To enable logging in Minimal APIs, you can use the built-in logging functionality provided by ASP.NET
Core.
var logger = builder.Services.GetRequiredService<ILogger<Program>>(); csharp

app.MapGet("/log", () =>
{
logger.LogInformation("This is an information log.");
return Results.Ok("Logged an info message.");
});

By default, ASP.NET Core will log to the console, but you can configure it to log to other destinations like a file or
a database.

Asynchronous Programming in ASP.NET Core Minimal API


Minimal APIs support asynchronous programming, allowing you to write non-blocking code for I/O operations like
database access, file handling, etc.
1. Async Endpoint Example: Here's an example of an asynchronous API endpoint using async and await :
app.MapGet("/async", async () => csharp
{
await Task.Delay(1000); // Simulate a delay
return Results.Ok("Async operation completed.");
});

2. Asynchronous Database Call (with Entity Framework Core): If you're using Entity Framework Core for data
access, you can define async endpoints like this:
app.MapGet("/users", async (ApplicationDbContext db) => csharp
{
var users = await db.Users.ToListAsync();
return Results.Ok(users);
});

ASP.NET Core Minimal API using Entity Framework Core


To use Entity Framework Core (EF Core) with a Minimal API, you'll first need to install the necessary NuGet packages
and set up a database context.
1. Install EF Core NuGet Packages:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer bash
dotnet add package Microsoft.EntityFrameworkCore.Tools

2. Create a DbContext and Model:


public class ApplicationDbContext : DbContext csharp
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : b
ase(options) { }

public DbSet<User> Users { get; set; }


}

public class User


{
public int Id { get; set; }
public string Name { get; set; }
}

3. Configure DbContext in Program.cs :


builder.Services.AddDbContext<ApplicationDbContext>(options => csharp
options.UseSqlServer("YourConnectionString"));

var app = builder.Build();

4. Define CRUD Operations:


app.MapGet("/users", async (ApplicationDbContext db) => csharp
{
return Results.Ok(await db.Users.ToListAsync());
});

app.MapPost("/users", async (ApplicationDbContext db, User user) =>


{
db.Users.Add(user);
await db.SaveChangesAsync();
return Results.Created($"/users/{user.Id}", user);
});

Endpoint Filters in ASP.NET Core Minimal API


Endpoint filters allow you to define reusable logic that can be applied to multiple API routes. They can be useful for
tasks like logging, authentication, validation, etc.
1. Custom Endpoint Filter Example: You can create a custom filter that logs the request details:
var logFilter = async (context, next) => csharp
{
var request = context.Request;
var method = request.Method;
var path = request.Path;
Console.WriteLine($"Request: {method} {path}");
await next();
};

app.Use(logFilter);

2. Apply Endpoint Filters: You can apply endpoint filters to specific routes or globally.
csharp
app.MapGet("/secure", [Authorize] () => Results.Ok("This is a secure endpoint."));

JWT Authentication in ASP.NET Core Minimal API


JWT (JSON Web Token) is a popular method for securing APIs. In ASP.NET Core, you can easily configure JWT
authentication for your Minimal APIs.
1. Install NuGet Packages:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer bash

2. Configure JWT Authentication in Program.cs :


builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) csharp
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.Authority = "https://your-auth-server";
options.Audience = "your-api";
});

3. Protect an Endpoint with JWT:


app.MapGet("/secure", [Authorize] () => Results.Ok("This is a secure endpoint."));
csharp

4. Generate JWT Tokens: You can also create a route to generate JWT tokens for user login:
app.MapPost("/login", (UserLogin login) => csharp
{
var claims = new[]
{
new Claim(ClaimTypes.Name, login.Username),
new Claim(ClaimTypes.Role, "User")
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secret-key"));


var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(


issuer: "your-issuer",
audience: "your-audience",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);

return Results.Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token)


});
});

API Versioning in ASP.NET Core Minimal API


API versioning allows you to manage multiple versions of your API, ensuring that clients can continue using older
versions while new features are added.
1. Install API Versioning NuGet Package:
dotnet add package Microsoft.AspNetCore.Mvc.Versioning bash

2. Configure API Versioning in Program.cs :


builder.Services.AddApiVersioning(options => csharp
{
options.ReportApiVersions = true;
});

3. Define Versioned Endpoints:


You can version your API routes by using a versioning scheme, such as query string, header, or URL path.
Query String Versioning:
app.MapGet("/api/products", () => new { Version = "v1" }).WithMetadata(new ApiVersi
csharp
onModel("1.0"));

URL Path Versioning:


app.MapGet("/api/v2/products", () => new { Version = "v2" }); csharp

4. Versioning Header: You can also define versioning based on request headers:
app.MapGet("/products", () => new { Version = "1.0" }) csharp
.WithMetadata(new ApiVersionModel("1.0"));

By leveraging Minimal APIs in ASP.NET Core, you can create lightweight, efficient, and simple RESTful APIs, while
integrating advanced features like JWT authentication, error handling, logging, asynchronous programming, and
API versioning easily. This setup is perfect for modern microservice architectures or small-to-medium scale
applications.
Build ASP.NET Core Web API Project From Scratch
Creating an ASP.NET Core Web API from scratch is a straightforward process using the .NET CLI or Visual Studio.
Here, we'll walk through building a Web API project step by step using the .NET CLI.
Steps to Build an ASP.NET Core Web API Project from Scratch
1. Create a New ASP.NET Core Web API Project
Open a terminal and use the .NET CLI to create a new Web API project:
dotnet new webapi -n MyApi bash
cd MyApi

This creates a folder called MyApi with the default Web API template.
2. Run the Application
To run the application:
dotnet run bash

You should see the API running on http://localhost:5000 or a similar URL. The default template includes a
basic WeatherForecast API.

Adding Web Host Builder


In ASP.NET Core, the Web Host Builder is used to configure and run the application. It's responsible for configuring
the server and starting the application.
In ASP.NET Core 3.1 and earlier, the WebHost was used to configure and run the application. However, starting from
ASP.NET Core 5, the HostBuilder was simplified to WebApplication.CreateBuilder() for convenience.
1. Example Using WebApplication.CreateBuilder() :
In .NET 6 and later, the Web Host Builder is simplified and integrated directly into the Program.cs file. Here's
how you would set up the host builder:
var builder = WebApplication.CreateBuilder(args); csharp

// Add services to the container.


builder.Services.AddControllers();

// Add Swagger to the container for API documentation.


builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.


if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();

app.MapControllers();

app.Run();

WebApplication.CreateBuilder(args) initializes a new builder for the application.


app.MapControllers() maps API controller endpoints.

app.Run() starts the application.


Configuring Startup Class in ASP.NET Core
In ASP.NET Core 3.x and earlier, the Startup.cs class was used to configure services and middleware. However,
starting with ASP.NET Core 6, this configuration has been simplified and merged into the Program.cs file,
following the "minimal API" approach.
Configuring Startup in ASP.NET Core 3.x and Earlier:
Here is how the Startup.cs class looks in older versions of ASP.NET Core:
1. Startup.cs:
public class Startup csharp
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
// Add services to the container
services.AddControllers();
services.AddSwaggerGen();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
}
}

2. Program.cs (For older versions, you would use this to call the Startup class):
public class Program csharp
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>


Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}

Starting with ASP.NET Core 6, the configuration has been streamlined, and we now have everything inside
Program.cs .

Adding Controller in ASP.NET Core


In ASP.NET Core, controllers are used to handle incoming HTTP requests and return responses. Controllers are
defined as classes with ControllerBase as the base class for Web APIs.
1. Create a New Controller:
To create a new controller, add a class to the Controllers folder in your project. The controller class should
inherit from ControllerBase .
using Microsoft.AspNetCore.Mvc; csharp

namespace MyApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
// In-memory products list for demonstration
private static readonly List<string> Products = new List<string>
{
"Product1", "Product2", "Product3"
};

// GET: api/products
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return Ok(Products);
}
// GET: api/products/1
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
if (id < 0 || id >= Products.Count)
{
return NotFound();
}
return Ok(Products[id]);
}
}
}

2. Test the Controller:


After adding this controller, run the application and test it with tools like Postman or Swagger UI.
Access the endpoint GET /api/products to retrieve the list of products.

Why .NET 6?
.NET 6 is a Long-Term Support (LTS) release of the .NET platform, and it brings several important improvements and
new features to help developers build modern applications efficiently.
Here’s why .NET 6 is a good choice for building ASP.NET Core Web APIs:
1. Simplified Hosting Model: .NET 6 introduces the minimal API model, which simplifies the process of creating
and hosting APIs by reducing the need for multiple files like Startup.cs and Program.cs .
The simplified setup is especially useful for smaller applications or microservices that don't require complex
configurations.
2. Unified Platform: .NET 6 unifies .NET Framework, .NET Core, and Xamarin into a single platform, which makes it
easier to develop applications across different platforms (Windows, macOS, Linux, Android, iOS, etc.).
3. Performance Improvements:
.NET 6 brings significant performance improvements over previous versions of .NET Core, especially in
terms of web APIs and server-side applications.
It has faster startup times, reduced memory usage, and improved throughput.
4. Cross-Platform Support: .NET 6 provides full cross-platform support, so you can develop and deploy
applications on Windows, Linux, and macOS without any compatibility issues.
5. C# 10 Features:
.NET 6 includes C# 10, which brings features like global using directives, file-scoped namespaces, and
improved pattern matching that help make your code cleaner and more concise.
6. Long-Term Support (LTS):
.NET 6 is an LTS release, meaning Microsoft will provide support and security updates for at least three
years (until November 2024).
7. Integration with Latest Libraries: .NET 6 integrates the latest libraries for technologies like Entity Framework
Core, SignalR, gRPC, and Blazor. This ensures that you can build modern applications with the most up-to-date
tools and frameworks.
8. Built-in Tools for Modern Development:
Hot Reload for rapid development.
Minimal API for quick API development.
Improved Diagnostic tools.
Better Blazor support for client-side development.
9. Better Cloud Integration:
With .NET 6, cloud services and microservices are made easier, as it includes libraries and tools to integrate
with popular cloud providers like Azure, AWS, and Google Cloud.

Summary
1. Build ASP.NET Core Web API: Create your Web API from scratch using the dotnet new webapi command.
2. Add Web Host Builder: In .NET 6, configure the Web Host in Program.cs to set up the application.
3. Configure Startup Class: In earlier versions, Startup.cs handled configuration, but now it's done directly in
Program.cs for simplicity.

4. Adding Controller: Create a controller class with [ApiController] to handle HTTP requests.
5. Why .NET 6: The latest LTS version provides performance improvements, simplicity, cross-platform support, and
enhanced tools for modern web application development.
By leveraging .NET 6, developers can build faster, cleaner, and more efficient Web APIs with minimal overhead.
Middleware in ASP.NET Core Web API
Middleware in ASP.NET Core refers to components that are used to handle requests and responses in a pipeline. They
are invoked in the order they are added to the pipeline in the Configure method of the Startup class (or directly
in Program.cs for .NET 6+). Middleware can handle things like authentication, logging, error handling, request
modification, and more.
Each piece of middleware is responsible for either passing the request to the next middleware in the pipeline or
handling the request and returning a response.
Core Concepts of Middleware
1. Request Handling: Middleware handles incoming requests and can modify the request before passing it along to
the next middleware in the pipeline.
2. Response Handling: Middleware can also modify the response before sending it back to the client.
3. Order of Execution: Middleware is executed in the order it is configured. This order is important, especially for
authentication, logging, and exception handling.
Run, Use, and Next Method in ASP.NET Core
ASP.NET Core provides three primary methods to work with middleware: Use , Run , and Map . These methods are
part of the IApplicationBuilder class, and they allow you to define and configure how middleware behaves in the
request-response pipeline.
1. Use Method
The Use method is used to add middleware components to the pipeline. Middleware added with Use must
call next() to pass the request to the next middleware in the pipeline.
Example:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.Use(async (context, next) =>
{
// Custom logic before request is passed to the next middleware
Console.WriteLine("Before Request");

// Pass control to the next middleware


await next.Invoke();

// Custom logic after request has passed through the pipeline


Console.WriteLine("After Response");
});
}

The next.Invoke() method is necessary for passing control to the next middleware.
This pattern is often used for logging, authentication, and error handling.
2. Run Method
The Run method is a terminal middleware, meaning it doesn’t pass control to the next middleware. Once Run
is called, it finishes the request pipeline processing.
Example:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello from Run middleware!");
});
}

The Run method is useful when you need to handle a request completely, without invoking other
middleware after it.
3. Next Method
The next method is used within custom middleware to pass control to the next middleware in the pipeline. It is
often used in the Use method as shown above.
app.Use(async (context, next) => csharp
{
// Perform something before
await next.Invoke(); // Call the next middleware in the pipeline
// Perform something after
});

Map Method in ASP.NET Core


The Map method is used to branch the request pipeline based on a specific condition (like a request path). If the
condition matches, the request is handled by a different set of middleware.
Example:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.Map("/admin", adminApp =>
{
adminApp.Run(async context =>
{
await context.Response.WriteAsync("Welcome to the Admin Section");
});
});

app.Map("/user", userApp =>


{
userApp.Run(async context =>
{
await context.Response.WriteAsync("Welcome to the User Section");
});
});

app.Run(async context =>


{
await context.Response.WriteAsync("Welcome to the Main Section");
});
}

Path-based branching: In the above example, requests to /admin will be handled by the /admin
middleware, and requests to /user will be handled by the /user middleware. All other requests will be
handled by the final Run middleware.
Custom Middleware in ASP.NET Core
Custom middleware in ASP.NET Core is a powerful feature that lets you define your own request and response
processing logic.
You can create custom middleware by defining a class with an Invoke or InvokeAsync method that takes an
HttpContext object and a next delegate.

Steps to Create Custom Middleware


1. Define the Custom Middleware Class:
public class MyCustomMiddleware csharp
{
private readonly RequestDelegate _next;

public MyCustomMiddleware(RequestDelegate next)


{
_next = next;
}

public async Task InvokeAsync(HttpContext httpContext)


{
// Custom logic before passing control to the next middleware
Console.WriteLine("Request is being processed");

// Call the next middleware in the pipeline


await _next(httpContext);

// Custom logic after the next middleware has completed


Console.WriteLine("Response is being processed");
}
}

2. Register the Custom Middleware in the Configure Method:


In the Startup.cs file (or Program.cs for .NET 6+), you register your custom middleware to be executed in
the request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.UseMiddleware<MyCustomMiddleware>();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
The UseMiddleware method adds your custom middleware to the pipeline.
The middleware logic will be executed for every request that comes into the application, allowing you to
modify the request or response as needed.
Example of Logging Middleware:
public class RequestLoggingMiddleware csharp
{
private readonly RequestDelegate _next;

public RequestLoggingMiddleware(RequestDelegate next)


{
_next = next;
}

public async Task InvokeAsync(HttpContext context)


{
Console.WriteLine($"Request made to {context.Request.Path}");

// Call the next middleware in the pipeline


await _next(context);

Console.WriteLine($"Response status: {context.Response.StatusCode}");


}
}

To use this logging middleware, you would register it as shown:


public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.UseMiddleware<RequestLoggingMiddleware>();

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

Summary
Middleware: Handles HTTP requests and responses, typically used for authentication, logging, exception
handling, etc.
Use: Adds middleware that invokes the next middleware in the pipeline.
Run: Adds terminal middleware that does not call the next middleware.
Map: Branches the pipeline based on a specific request condition (e.g., request path).
Custom Middleware: Allows you to define custom logic to handle requests and responses. You can create a
custom class implementing logic in the InvokeAsync method and add it to the pipeline using
UseMiddleware .

This flexibility in ASP.NET Core Web API's middleware system allows you to customize and extend the request-
processing pipeline to suit your needs.
Microservices using ASP.NET Core
Microservices is an architectural style that structures an application as a collection of loosely coupled, independently
deployable services. Each microservice typically focuses on a single business capability, is independently scalable,
and can be developed using different technologies. ASP.NET Core provides a robust framework to build
microservices with features like high performance, cross-platform support, and modular architecture.

Core Concepts of Microservices


1. Decomposition:
Microservices break down large, monolithic applications into small, independent services. Each service
focuses on a specific business capability and can be developed, deployed, and scaled independently.
2. Distributed Systems:
Microservices are usually distributed systems where different services communicate with each other over
HTTP/REST, messaging queues, or other communication protocols.
3. Domain-Driven Design (DDD):
Microservices often map closely to business domains. The domain model of the application is split into
multiple bounded contexts, each represented by a different microservice.
4. Independent Deployment:
Each microservice can be deployed and scaled independently, allowing faster releases and scaling based
on specific service requirements.
5. Inter-Service Communication:
Microservices communicate using lightweight protocols such as HTTP, REST, and messaging queues like
RabbitMQ, Kafka, or Azure Service Bus.
6. Data Ownership:
Each microservice manages its own data and database, ensuring independence and encapsulation.

Benefits of Microservices in ASP.NET Core


1. Scalability:
Microservices allow for independent scaling. If one microservice requires more resources, it can be scaled
without affecting the other services.
2. Faster Development:
Development teams can work independently on different microservices, improving productivity and
reducing the time to market.
3. Technology Agnostic:
Each microservice can be built using different technologies or frameworks. For example, one service might
use ASP.NET Core, while another uses Node.js or Java.
4. Fault Isolation:
If one service fails, it doesn’t impact other services in the system. This isolation leads to higher resilience
and availability.
5. Improved Maintainability:
Microservices are smaller in size and scope, making it easier to understand, modify, and maintain over time.

Creating Microservices Using ASP.NET Core


To implement a microservices architecture in ASP.NET Core, you need to follow some best practices and utilize
several patterns and tools. Here’s a step-by-step guide to building a basic microservice-based application in
ASP.NET Core.

Steps to Build Microservices with ASP.NET Core


1. Setting Up the Microservices
Each microservice is typically a separate ASP.NET Core project. You might have several microservices that
communicate with each other. For example:
Service A: Product Management Microservice
Service B: Order Management Microservice
Service C: Payment Gateway Microservice
You can start by creating a new ASP.NET Core Web API project for each service.
dotnet new webapi -n ProductService bash
dotnet new webapi -n OrderService
dotnet new webapi -n PaymentService

2. Service Communication
Microservices communicate with each other through HTTP or messaging systems like RabbitMQ, Kafka, etc. In this
example, we’ll use HTTP for inter-service communication.
RESTful APIs: Each microservice exposes a set of REST APIs that other services can consume.
Example of an API for a Product Service:
[ApiController] csharp
[Route("api/products")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;

public ProductsController(IProductService productService)


{
_productService = productService;
}

[HttpGet]
public async Task<IActionResult> GetAllProducts()
{
var products = await _productService.GetProductsAsync();
return Ok(products);
}
}

For inter-service communication, you can use HttpClient to call the APIs of other services:
public class OrderService csharp
{
private readonly HttpClient _httpClient;

public OrderService(HttpClient httpClient)


{
_httpClient = httpClient;
}

public async Task CreateOrderAsync(Order order)


{
var response = await _httpClient.GetAsync("http://productservice/api/product
s");
if (response.IsSuccessStatusCode)
{
var products = await response.Content.ReadAsAsync<IEnumerable<Product>>();
// Process products and create order logic
}
}
}

3. Database per Service


Each microservice should have its own database to ensure that they are loosely coupled. This can be a relational
database like SQL Server, PostgreSQL, or a NoSQL database like MongoDB.
In the Product Service, for example, you would configure its own database context:
public class ProductContext : DbContext csharp
{
public ProductContext(DbContextOptions<ProductContext> options) : base(options)
{
}

public DbSet<Product> Products { get; set; }


}

In the Startup.cs file of each service, you can configure the database connection for the specific service:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddDbContext<ProductContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ProductDatabase")));
}

4. Service Discovery
In a microservices environment, services need to find each other to communicate. There are multiple ways to handle
service discovery:
Static URLs: Hardcode the URLs of the services (not ideal in dynamic environments).
Service Registry: Use tools like Consul, Eureka, or HashiCorp Vault for dynamic service discovery.
Reverse Proxy: Use a reverse proxy like Nginx or Kong to manage requests to microservices.
For ASP.NET Core, you can integrate with tools like Consul for service discovery.
5. API Gateway
An API Gateway serves as a single entry point for the client to interact with microservices. It handles routing requests
to the appropriate microservices and can also provide additional functionality like rate limiting, load balancing, and
authentication.
For an API Gateway, you can use Ocelot with ASP.NET Core.
dotnet add package Ocelot bash

Create a ocelot.json file for routing configuration:


{ json
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/products",
"UpstreamPathTemplate": "/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "productservice",
"Port": 80
}
]
}
]
}

6. Security in Microservices
To secure communication between services, you can implement JWT Authentication. This ensures that only
authorized users or services can interact with your APIs.
Example of JWT authentication:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://your-identity-provider.com";
options.Audience = "microservices-api";
});

services.AddAuthorization();
}

You can also implement OAuth 2.0, Role-Based Access Control (RBAC), or API Key Authentication depending on
your use case.
7. Dockerizing Microservices
Microservices are typically containerized using Docker to achieve portability and scalability. You can create a
Dockerfile for each service to build its container.

Example Dockerfile for the Product Service:


FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base dockerfile
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build


WORKDIR /src
COPY ["ProductService/ProductService.csproj", "ProductService/"]
RUN dotnet restore "ProductService/ProductService.csproj"
COPY . .
WORKDIR "/src/ProductService"
RUN dotnet build "ProductService.csproj" -c Release -o /app/build

FROM build AS publish


RUN dotnet publish "ProductService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProductService.dll"]

You can then build and run the Docker containers for each microservice and the API Gateway (if used).

Key Considerations for Microservices in ASP.NET Core


1. Fault Tolerance:
Use tools like Polly to implement retries, circuit breakers, and fallbacks to handle transient faults when
making requests between services.
2. Distributed Tracing:
Use distributed tracing with tools like Jaeger or Zipkin to trace requests across multiple microservices.
3. Event-Driven Architecture:
Use messaging queues like RabbitMQ, Azure Service Bus, or Kafka for event-driven architectures where
services communicate asynchronously via events.
4. Resilience:
Ensure that your services are resilient to failure. Implement mechanisms like retries, timeouts, and circuit
breakers to handle failures gracefully.
5. Centralized Logging:
Use a centralized logging solution such as Elastic Stack (ELK), Splunk, or Serilog for collecting and
analyzing logs from all microservices.

Conclusion
Building microservices using ASP.NET Core is a powerful approach for modern, scalable, and maintainable
applications. By decomposing a monolithic application into smaller, self-contained services, you gain flexibility,
independent scaling, and improved fault tolerance. However, building and managing microservices comes with
challenges, such as handling inter-service communication, managing data consistency, and ensuring security.
By leveraging the tools and frameworks within the ASP.NET Core ecosystem, you can build high-performance
microservices that are easy to maintain and scale.
Here is a comprehensive guide to ASP.NET Core Web API Interview Questions and Answers at various levels:

ASP.NET Core Web API Basic Interview Questions and Answers


1. What is ASP.NET Core Web API?
Answer:
ASP.NET Core Web API is a framework for building HTTP services that can be accessed from any client. It is part of
the ASP.NET Core framework and allows you to build RESTful APIs that can be consumed by web clients, mobile
devices, desktop apps, or other servers. It is lightweight, cross-platform, and supports modern web standards like
JSON and XML.

2. What is the difference between ASP.NET Web API and ASP.NET Core Web API?
Answer:
ASP.NET Web API is a framework for building HTTP-based services in the traditional ASP.NET framework (older,
Windows-only).
ASP.NET Core Web API is a modern, cross-platform framework built on ASP.NET Core, which works on
Windows, Linux, and macOS. It is more lightweight and faster, with improved performance and better support for
dependency injection, modularity, and configuration.

3. What is the purpose of the Controller in ASP.NET Core Web API?


Answer:
In ASP.NET Core Web API, a Controller is a class responsible for handling HTTP requests. Each action method inside
the controller corresponds to an HTTP request (GET, POST, PUT, DELETE, etc.). The controller interacts with the
model and returns a response (like JSON, XML, etc.) to the client.
Example:
[ApiController] csharp
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok(new { message = "Hello, World!" });
}
}

4. What is an HTTP verb in Web API?


Answer:
HTTP verbs (also known as HTTP methods) specify the type of action that the client wants to perform on a resource.
Common HTTP verbs include:
GET: Retrieve data.
POST: Create a new resource.
PUT: Update an existing resource.
DELETE: Remove a resource.
PATCH: Partially update a resource.

5. What is Swagger in ASP.NET Core Web API?


Answer:
Swagger is a tool used for documenting and testing APIs. In ASP.NET Core Web API, you can use Swashbuckle to
generate Swagger UI, which automatically creates interactive API documentation for your endpoints. It helps
developers and clients understand the available endpoints and test them directly from the browser.
Example:
dotnet add package Swashbuckle.AspNetCore bash

In Startup.cs, enable Swagger:


public void ConfigureServices(IServiceCollection services) csharp
{
services.AddSwaggerGen();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
app.UseSwagger();
app.UseSwaggerUI();
}

ASP.NET Core Web API Intermediate Interview Questions and Answers


1. What is Dependency Injection in ASP.NET Core Web API?
Answer:
Dependency Injection (DI) is a design pattern where objects are passed to a class, rather than being created inside it.
In ASP.NET Core, DI is built-in and is used to provide services (like database contexts, business logic, etc.) to classes
(like controllers and middleware). This promotes loose coupling, testability, and modularity.
Example:
public class ProductController : ControllerBase csharp
{
private readonly IProductService _productService;

public ProductController(IProductService productService)


{
_productService = productService;
}

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

In Startup.cs, register the service:


public void ConfigureServices(IServiceCollection services) csharp
{
services.AddScoped<IProductService, ProductService>();
}

2. What is Model Binding in ASP.NET Core Web API?


Answer:
Model Binding in ASP.NET Core Web API refers to the process of mapping data from an HTTP request to a method
parameter in a controller. It automatically binds query parameters, route data, form data, and the request body to the
method’s parameters. This allows developers to focus on business logic without worrying about the specifics of data
extraction.
Example:
[HttpPost] csharp
public IActionResult CreateProduct([FromBody] Product product)
{
// Product is automatically bound from the request body
_productService.Create(product);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

3. What is the difference between IActionResult and ActionResult<T> in ASP.NET Core Web API?
Answer:
IActionResult is a base interface that represents the result of an action method in a controller. It is flexible
and can return different types of responses (e.g., Ok() , BadRequest() , NotFound() ).
ActionResult<T> is a specialized type that allows returning a strongly typed response, combining
IActionResult and a value. It is useful when you need to return data along with a status code.
Example:
// IActionResult csharp
public IActionResult GetProduct(int id) { ... }

// ActionResult<T>
public ActionResult<Product> GetProduct(int id) { ... }

4. What is Routing in ASP.NET Core Web API?


Answer:
Routing in ASP.NET Core Web API is the process of matching an incoming HTTP request to a corresponding controller
action. Routes are defined in the controller using route attributes like [Route] or through convention-based routing.
Routes can also include parameters.
Example of route:
[Route("api/products/{id}")] csharp
public IActionResult GetProduct(int id)
{
var product = _productService.GetProductById(id);
return product == null ? NotFound() : Ok(product);
}

5. What is the app.UseRouting() and app.UseEndpoints() in ASP.NET Core Web API?


Answer:
app.UseRouting() : This middleware is responsible for routing the request to the appropriate endpoint. It
maps the HTTP request to a controller action based on the routing rules.
app.UseEndpoints() : This middleware is used to define the endpoints that the application will respond to. It
connects the routing configuration to actual controller actions.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
ASP.NET Core Web API Advanced Interview Questions and Answers
1. What is the difference between AddSingleton , AddScoped , and AddTransient in ASP.NET Core?
Answer:
AddSingleton : The service is created once and shared across all requests. It is a singleton instance.

AddScoped : The service is created once per request (per scope). It is shared within the same request but not
across requests.
AddTransient : A new instance of the service is created every time it is requested.

Example:
services.AddSingleton<ISingletonService, SingletonService>(); csharp
services.AddScoped<IScopedService, ScopedService>();
services.AddTransient<ITransientService, TransientService>();

2. What is CORS, and how do you enable it in ASP.NET Core Web API?
Answer:
CORS (Cross-Origin Resource Sharing) is a security feature that allows or restricts resources from being requested
from another domain. It is useful when you need to allow external clients (e.g., a frontend on a different domain) to
interact with your API.
To enable CORS:
1. Define CORS policies in Startup.cs :
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddCors(options =>
{
options.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)


{
app.UseCors("AllowAll");
}

2. Apply CORS to controllers or actions using the [EnableCors] attribute.


3. Explain the concept of Async/Await in ASP.NET Core Web API.
Answer:
Async/Await allows for non-blocking I/O operations, improving the scalability of the application. When you use
async with methods and await with asynchronous calls, the thread doesn’t block while waiting for I/O operations
(such as database calls or HTTP requests) to complete. This improves performance by allowing the server to handle
other requests in the meantime.
Example:
[HttpGet] csharp
public async Task<IActionResult> GetProductsAsync()
{
var products = await _productService.GetProductsAsync();
return Ok(products);
}

4. What is the role of app.UseEndpoints() in configuring routing in ASP.NET Core?


Answer:
The app.UseEndpoints() method is used in the Configure method of Startup.cs to define and map the
endpoints for the application, such as controllers, Razor Pages, or SignalR hubs. This method connects the routing
middleware to the actual request
-handling logic.
Example:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) csharp
{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}

5. What is Dependency Injection, and how is it used in ASP.NET Core Web API?
Answer:
Dependency Injection (DI) is a design pattern where a class receives its dependencies (services, data, etc.) rather
than creating them internally. In ASP.NET Core, DI is built into the framework and allows services like database
contexts, logging, and business logic to be injected into controllers, middleware, or other components.
Example:
public class ProductController : ControllerBase csharp
{
private readonly IProductService _productService;

public ProductController(IProductService productService)


{
_productService = productService;
}
}

In Startup.cs:
public void ConfigureServices(IServiceCollection services) csharp
{
services.AddScoped<IProductService, ProductService>();
}

These questions and answers will help you prepare for ASP.NET Core Web API interviews at various experience
levels, from beginners to advanced.

You might also like