Unit 5: ASP.NET Core MVC, Entity Framework Core and Security
I. Orientation — The ASP.NET Core Web Application Model
ASP.NET Core is a cross-platform framework for building web applications and APIs. Its design combines an HTTP request pipeline, built-in dependency injection, MVC separation of concerns, and Entity Framework Core for database access. Security is applied through authenticated identities and authorization policies before protected resources are executed.
- Request-driven execution: A client sends an HTTP request; middleware processes it and eventually produces an HTTP response.
- Separation of responsibilities: Controllers handle application requests, models represent data and rules, and views render HTML.
- Inversion of control: Application classes receive dependencies through constructors instead of creating them directly.
- ORM-based persistence: Entity Framework Core maps .NET objects to relational database tables.
- Explicit security decisions: Authentication identifies a user; authorization determines whether that user may perform an operation.
- Configuration by environment: Development, testing, and production can use different connection strings, middleware, and logging settings.
II. Middleware Request Pipeline — Ordered HTTP Processing
Middleware components are software units arranged in sequence. Each component can inspect or modify an HTTP request, call the next component, and inspect or modify the response on the way back.
A. Middleware Request Pipeline
The middleware request pipeline determines how every request travels through an ASP.NET Core application.
- Sequential execution: Middleware is registered in
Program.csand runs in registration order. - Request and response stages: A component executes code before
next(), transfers control throughnext(), and can execute response logic afterward. - Short-circuiting: A middleware component may create a response without calling the next component, such as returning
401 Unauthorized. - Order dependency:
UseRouting()must occur before endpoint authorization, whileUseAuthentication()must precedeUseAuthorization(). - Terminal execution:
MapGet,MapControllers, or endpoint middleware can finish the pipeline.
app.Use(async (context, next) =>
{
Console.WriteLine("Before endpoint");
await next();
Console.WriteLine("After endpoint");
});
app.MapGet("/", () => "Hello");Here, context is the current HttpContext, and next represents the remaining pipeline.
B. Built-In Middleware and Custom Middleware
Built-in middleware supplies common web infrastructure, while custom middleware implements application-specific cross-cutting behavior.
- Exception handling:
app.UseExceptionHandler("/Error")provides centralized production error handling. - HTTPS enforcement:
app.UseHttpsRedirection()redirects HTTP requests to HTTPS. - Static files:
app.UseStaticFiles()serves files from thewwwrootdirectory. - Routing:
app.UseRouting()matches URLs to endpoints. - Authentication and authorization: These middleware components establish identity and enforce access rules.
- Custom middleware class: A class conventionally contains a
RequestDelegateand anInvokeAsyncmethod.
public sealed class RequestTimingMiddleware
{
private readonly RequestDelegate _next;
public RequestTimingMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
var start = DateTime.UtcNow;
await _next(context);
Console.WriteLine(DateTime.UtcNow - start);
}
}Register it with app.UseMiddleware<RequestTimingMiddleware>(). Middleware is useful for logging, correlation IDs, exception handling, and request validation; it should not contain controller-specific business logic.
III. Dependency Injection in ASP.NET Core — Supplying Application Services
Dependency injection (DI) is a technique in which a class receives required services from an external container. ASP.NET Core includes a built-in service container that constructs objects and manages their lifetimes.
A. Dependency Injection in ASP.NET Core
DI reduces coupling by allowing classes to depend on interfaces or abstractions rather than concrete implementations.
- Constructor injection: Dependencies are declared in a constructor, making required services explicit.
- Service registration:
AddTransient,AddScoped, andAddSingletonregister services with different lifetimes. - Transient lifetime: A new instance is created each time the service is requested; suitable for lightweight stateless services.
- Scoped lifetime: One instance is created per HTTP request;
DbContextis normally scoped. - Singleton lifetime: One instance exists for the application lifetime; it must be thread-safe and must not depend on scoped services.
- Controller activation: MVC obtains controller dependencies from the service container automatically.
builder.Services.AddScoped<IOrderService, OrderService>();
public class OrdersController : Controller
{
private readonly IOrderService _orders;
public OrdersController(IOrderService orders) => _orders = orders;
}The interface IOrderService defines the dependency, and OrderService is the registered implementation. Incorrect lifetimes can cause stale data, memory retention, or attempts to use scoped objects from singletons.
IV. Entity Framework Core — Object-Relational Data Access
Entity Framework Core (EF Core) is a .NET object-relational mapper (ORM). It enables applications to query and update relational databases using C# objects and LINQ while still supporting SQL database features.
A. Introduction to Entity Framework Core
EF Core maps entity classes and relationships to database structures and translates LINQ expressions into provider-specific SQL.
- Entity: A class such as
Productrepresents a row concept in a database table. - Property mapping: A property such as
Namenormally maps to a column namedName. - LINQ translation:
context.Products.Where(p => p.Price > 100)is translated into a database query. - Change tracking: EF Core detects added, modified, and deleted entities before
SaveChangesAsync(). - Provider model: Packages such as
Microsoft.EntityFrameworkCore.SqlServerconnect EF Core to a specific database engine. - Deferred execution: An
IQueryablequery generally executes when enumerated, for example withToListAsync().
B. DbContext and Entity Configuration
DbContext represents a session with the database and coordinates querying, tracking, configuration, and persistence.
- DbSet properties: A
DbSet<Product> Productsproperty exposes product records for querying. - Connection configuration:
AddDbContext<AppDbContextuses a connection string stored in configuration. - Model configuration:
OnModelCreatingdefines keys, lengths, precision, relationships, and constraints. - Fluent API priority: Fluent configuration is centralized and can override conventions and data annotations.
- Relationship mapping: A foreign key such as
CategoryIdconnects aProductto aCategory.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasKey(p => p.Id);
modelBuilder.Entity<Product>()
.Property(p => p.Price)
.HasPrecision(18, 2)
.IsRequired();
}Here, Id is the primary key and Price is stored with 18 total digits and 2 decimal places.
C. Code First Approach
The Code First Approach begins with C# entity classes and generates or updates the database schema from the model.
- Model as source: Developers define classes, keys, navigation properties, and constraints in code.
- Schema generation: EF Core migrations convert model changes into database operations.
- Advantages: Code First supports version control, automated deployment, and domain-driven modeling.
- Relationship example:
public int CategoryId { get; set; }andpublic Category Category { get; set; }express a product-category relationship. - Best use: It is appropriate when the application owns a new database or the schema changes frequently.
D. Database First Approach
The Database First Approach begins with an existing database and generates entity classes and a DbContext from its schema.
- Reverse engineering:
dotnet ef dbcontext scaffoldreads tables, keys, and relationships. - Existing schema: It is useful when a database already belongs to an organization or legacy system.
- Generated artifacts: Scaffolded classes describe database tables; partial classes can preserve custom code across regeneration.
- Tradeoff: Database changes must be reflected by repeating or managing scaffolding carefully.
- Best use: It suits applications integrating with a stable, pre-existing relational database.
E. Database Migrations
Database migrations provide versioned, repeatable transformations between EF Core model states and database schemas.
- Create migration:
dotnet ef migrations add InitialCreaterecords the initial model. - Apply migration:
dotnet ef database updateexecutes pending migrations against the configured database. - Migration contents: A migration commonly contains
Up, which applies changes, andDown, which reverses them. - Schema history: EF Core stores applied migration names in a history table.
- Deployment discipline: Review generated SQL and apply migrations through controlled deployment processes rather than relying blindly on application startup.
- Concrete change: Adding
DescriptiontoProductmay generate anAddColumnoperation.
F. CRUD Operations using Entity Framework Core
CRUD means Create, Read, Update, and Delete; EF Core implements these operations through a DbContext.
- Create: Add an object to a
DbSet, then persist it. - Read: Use LINQ and asynchronous methods such as
SingleOrDefaultAsync. - Update: Load a tracked entity, change its properties, and call
SaveChangesAsync. - Delete: Remove the entity and save the resulting deletion.
- Validation and concurrency: Validate input before saving and handle missing rows or concurrency conflicts.
_context.Products.Add(product); // Create
var item = await _context.Products.FindAsync(id); // Read
item.Price = 29.99m; // Update
_context.Products.Remove(item); // Delete
await _context.SaveChangesAsync();In practice, each operation is normally performed in a separate request, with null checks and authorization before modifying records.
V. Authentication and Authorization in Web Applications — Protecting Resources
Web application security separates identity verification from permission checking. Authentication establishes who the requester is; authorization evaluates whether the identified principal can access a resource.
A. Authentication and Authorization in Web Applications
Authentication and authorization should be configured as coordinated but distinct stages.
- Authentication: A login process validates credentials and creates a cookie or token representing the user.
- Authorization: ASP.NET Core evaluates
[Authorize], roles, claims, or policies after authentication. - Anonymous access:
[AllowAnonymous]permits selected actions, such as a login action, to bypass authorization. - Cookie authentication: Browser applications commonly use an encrypted authentication cookie maintained by ASP.NET Core Identity.
- Bearer authentication: APIs commonly receive a JWT in the
Authorization: Bearer <token>header. - Claims and roles: A claim such as
Department=Financesupplies data for policy decisions; a role such asAdmingroups permissions. - Policy-based authorization: Policies express requirements more flexibly than role checks.
[Authorize(Policy = "CanEditProducts")]
public async Task<IActionResult> Edit(int id)
{
// Only an authenticated principal satisfying the policy reaches this action.
}A typical configuration calls app.UseAuthentication() before app.UseAuthorization(), followed by endpoint mapping. Passwords should never be stored in plain text; ASP.NET Core Identity uses password hashing, account management, and security-token support. HTTPS, antiforgery protection for cookie-based form posts, input validation, and least-privilege policies reduce common risks such as credential theft, cross-site request forgery, and unauthorized data changes.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →