ASP.net Interview P1
Interactive .NET Interview Guide
From ASP.NET Framework 4.6.1 to ASP.NET Core 8
Welcome to Your Interactive Study Guide
This guide is designed for an experienced .NET developer preparing for interviews. It covers both legacy ASP.NET Web API on the .NET Framework and modern ASP.NET Core Web API, offering a comprehensive look at building APIs, key concepts, and the critical differences between the two frameworks. Use the navigation above to jump between sections. The goal of this interactive format is to help you quickly compare frameworks and test your knowledge on advanced topics, making your interview preparation more effective.
Framework Deep Dive
Select a framework to explore its core concepts, architecture, and code examples.
ASP.NET Web API (.NET Framework 4.6.1)
1. Animated Architecture & Hosting
Web API is built on `System.Web`, making it intrinsically linked to the IIS pipeline. A request hits IIS, which passes it to the ASP.NET Runtime. This runtime processes the request through `HttpModules` and `HttpHandlers` before it reaches the Web API framework. The animation below shows this sequential flow.
2. `Global.asax` & Application Lifecycle
The `Global.asax.cs` file is the heart of application-level event handling. The `Application_Start` method is executed once when the application domain is first created. It's the primary location for registering all application-wide configurations, such as Web API routes, filters, and dependency injection containers.
3. `Web.config` Configuration
The `Web.config` file is an XML-based configuration file that controls almost every aspect of the application. It contains connection strings for databases, custom application settings in the `
4. `ApiController` Base Class
This is the fundamental base class for any API controller. It provides essential properties like `Request` (to inspect the incoming `HttpRequestMessage`), `User` (to access the security context of the user), and `Configuration` (to access the application's `HttpConfiguration`).
5. Routing (Convention-based)
Convention-based routing defines URL patterns globally in the `WebApiConfig.cs` file. The framework matches incoming URLs to controllers and actions based on their names. This approach promotes consistency but can be less flexible for complex APIs.
6. Routing (Attribute-based)
Attribute routing offers more fine-grained control by defining routes directly on controllers and actions. You must first enable it with `config.MapHttpAttributeRoutes()` in your `WebApiConfig`. `[RoutePrefix]` sets a base path for all actions in a controller, and `[Route]` defines the specific path for an action.
7. Action Verbs (`[HttpGet]`, `[HttpPost]`)
These attributes explicitly map an HTTP method to a controller action. While the framework can infer the method from the action name (e.g., a method named `GetProducts` is treated as a GET request), using attributes is clearer and avoids ambiguity.
8. Return Types (`IHttpActionResult`)
`IHttpActionResult` is an interface that acts as a factory for `HttpResponseMessage`. It simplifies controller actions by abstracting away the manual creation of response objects, leading to cleaner and more easily testable code. Helper methods on `ApiController` like `Ok()`, `NotFound()`, `BadRequest()`, and `StatusCode()` return concrete implementations of this interface.
9. Model Binding
Model binding is the magic that converts HTTP request data into strongly-typed .NET objects for your action method parameters. By default, simple types like `int`, `string`, and `bool` are bound from the URL's route data and query string. Complex types (classes) are assumed to come from the request body.
10. `[FromUri]` & `[FromBody]`
These attributes allow you to override the default model binding behavior. `[FromUri]` forces a parameter (even a complex type) to be bound from the URI, while `[FromBody]` forces a simple type to be read from the request body. An action can have at most one `[FromBody]` parameter.
11. Data Annotations & `ModelState`
You use attributes from `System.ComponentModel.DataAnnotations` (like `[Required]`, `[StringLength]`, `[Range]`) on your model properties to define validation rules. Inside your controller action, you must explicitly check the `ModelState.IsValid` property. If it's false, it means validation failed, and you should typically return a `BadRequest` response containing the validation errors.
12. Content Negotiation (`MediaTypeFormatter`)
Content negotiation is the process of selecting the best representation (e.g., JSON, XML) for a response based on the `Accept` header sent by the client. This is handled by a collection of `MediaTypeFormatter` instances. The default formatters are `JsonMediaTypeFormatter` and `XmlMediaTypeFormatter`.
13. Controller Lifecycle
For each request, a new controller instance is created by the `IHttpControllerActivator`. The framework's `HttpControllerDispatcher` selects the appropriate action, executes the filter pipeline, invokes the action method, and finally calls the `Dispose` method on the controller instance to clean up resources.
14. Filters - Action Filters
Action filters provide a way to inject logic immediately before (`OnActionExecuting`) and after (`OnActionExecuted`) a controller action is invoked. They are ideal for cross-cutting concerns like logging, performance monitoring, or modifying the action result.
15. Filters - Authorization Filters
Authorization filters run before any other filter. Their primary purpose is to check the identity and permissions of the user making the request. If the check fails, the filter can short-circuit the request and return a 401 Unauthorized or 403 Forbidden response.
16. Filters - Exception Filters
Exception filters are executed only when an unhandled exception is thrown from within the action execution pipeline. They provide a centralized place to log the exception and return a standardized, user-friendly error response instead of letting the application crash.
17. Filters - Order of Execution
The filter execution pipeline follows a clear order: 1. Authorization Filters, 2. Action Filters. If an exception occurs at any point, the flow is interrupted, and Exception Filters are executed.
18. Message Handlers (`DelegatingHandler`)
Message handlers are powerful, low-level components that operate on the raw `HttpRequestMessage` and `HttpResponseMessage`. They form a chain and are executed before the request even reaches the routing system, making them perfect for request-level concerns like API key validation, request/response logging, or adding custom headers.
19. Dependency Resolution (`IDependencyResolver`)
Since Web API doesn't have a built-in DI container, you must use a third-party library like Autofac or Unity. To integrate it, you create a wrapper class that implements `IDependencyResolver`. This wrapper tells Web API how to use your chosen container to create controller instances and resolve their dependencies.
20. CORS (Cross-Origin Resource Sharing)
To allow web browsers to make requests to your API from a different domain, you must explicitly enable CORS. This involves installing the `Microsoft.AspNet.WebApi.Cors` NuGet package, enabling it in your `WebApiConfig` with `config.EnableCors()`, and then applying the `[EnableCors]` attribute to your controllers or globally.
21. OWIN & Katana
OWIN (Open Web Interface for .NET) is a specification that decouples the web application from the web server. Katana is Microsoft's project that provides the components to build and host OWIN-based applications. This allows a Web API application to be self-hosted in a console application or Windows Service, freeing it from its dependency on IIS.
22. Authentication with OWIN Middleware
In a modern Web API 2 project, authentication is handled by OWIN middleware components, not by Web API filters. You create a `Startup.cs` class where you configure and chain authentication middleware, such as middleware for handling cookies, bearer tokens (JWT), or external providers like Google or Facebook.
23. API Versioning Strategies
Versioning is crucial for evolving an API without breaking existing clients. Common strategies include versioning via the URL path (`/api/v2/products`), a query string parameter (`/api/products?api-version=2.0`), or a custom request header (`X-API-Version: 2.0`). This is typically implemented using custom route constraints or third-party libraries.
24. Asynchronous Actions (`async`/`await`)
Using the `async` and `await` keywords in controller actions is essential for scalability. When an I/O-bound operation (like a database query or an external HTTP call) is awaited, the request thread is released back to the thread pool to serve other requests. Once the operation completes, a thread is used to resume processing the original request.
25. Web API Caching
Web API primarily supports client-side caching by allowing the developer to control cache-related HTTP headers. By setting headers like `Cache-Control` (e.g., `public, max-age=60`) and `ETag`, you can instruct browsers and proxy servers on how to cache the response, reducing subsequent requests to your server.
ASP.NET Core Web API (.NET 8)
1. Animated Architecture & Hosting
ASP.NET Core applications are self-contained console apps with a built-in Kestrel web server. This allows cross-platform deployment. The request pipeline is a series of middleware components you explicitly define in `Program.cs`, as shown in the animation.
2. `Program.cs` & Application Startup
With the modern "minimal hosting model," the `Program.cs` file is the unified entry point for the application. It's where you create a `WebApplicationBuilder` to configure services for dependency injection and then build a `WebApplication` instance to define the HTTP request pipeline middleware.
3. Middleware Pipeline
The request pipeline is composed of a series of middleware components, each defined by an `app.Use...` call in `Program.cs`. The order is critical. For example, `app.UseAuthentication()` must come before `app.UseAuthorization()` so that the user is identified before their permissions are checked.
4. Configuration System
The configuration system is a flexible, key-value based framework. It reads settings from a variety of sources in a hierarchical order: `appsettings.json`, then environment-specific files like `appsettings.Development.json`, followed by user secrets, environment variables, and command-line arguments. Later sources override earlier ones.
5. The Options Pattern (`IOptions`)
This pattern provides a strongly-typed way to access related groups of configuration settings. You define a class to hold your settings, bind it to a section of your configuration file, and then inject it into your services using `IOptions
6. Dependency Injection & Service Lifetimes
Dependency Injection is a first-class, built-in feature. Services are registered in the `IServiceCollection` with specific lifetimes that control their instantiation: Singleton (one instance for the entire application), Scoped (one instance per client request), and Transient (a new instance every time it is requested).
7. `ControllerBase` vs. `Controller`
For building APIs, you should inherit from `ControllerBase`. It provides the necessary functionality for handling HTTP requests (like access to `HttpContext`, `ModelState`, and helper methods for returning results). The `Controller` class inherits from `ControllerBase` and adds support for Views, which is unnecessary for a headless API and adds minor overhead.
8. Endpoint Routing
Endpoint routing decouples route matching from endpoint execution. The `app.UseRouting()` middleware inspects the incoming request and matches it to a specific endpoint (like a controller action). Later middleware (like `UseAuthentication` and `UseAuthorization`) can then access this routing information before the `app.UseEndpoints()` middleware finally executes the matched endpoint.
9. Action Verbs & Attribute Routing
Attribute routing is the standard and preferred method in ASP.NET Core. HTTP method attributes (`[HttpGet]`, `[HttpPost]`, etc.) combined with route templates (`[Route("...")]`) are used to explicitly and clearly define the URL and method for each endpoint.
10. Return Types (`ActionResult`)
This return type is a key feature for building clean and well-documented APIs. It allows an action method to return either a specific type `T` (which the framework will wrap in a 200 OK response) or any `IActionResult` (like `NotFound()`, `BadRequest()`). This provides strong typing for success cases, which tools like Swagger/OpenAPI use to generate accurate client code and documentation.
11. Model Binding & Sources
The model binding system is highly configurable. While it has smart defaults, you can use explicit attributes like `[FromRoute]`, `[FromQuery]`, `[FromHeader]`, and `[FromBody]` to tell the framework exactly where to find the data for a given parameter, removing any ambiguity.
12. `[ApiController]` Attribute & Conventions
Applying the `[ApiController]` attribute to your controllers enables a set of helpful, opinionated conventions that streamline API development. These include requiring attribute routing, automatically triggering model state validation, and inferring binding sources for parameters.
13. Validation & `ValidationProblemDetails`
When a controller is decorated with `[ApiController]`, the framework automatically checks `ModelState.IsValid`. If validation fails, it short-circuits the action and returns a 400 Bad Request with a standardized `ValidationProblemDetails` response body (RFC 7807), which clearly lists the validation errors in a machine-readable format.
14. Minimal APIs
Introduced in .NET 6, Minimal APIs provide a low-ceremony syntax for building HTTP endpoints directly in `Program.cs` using lambda expressions. This is ideal for microservices or simple APIs where the structure and features of controllers would be overkill.
15. Filters vs. Middleware
Middleware is lower-level, operates on the `HttpContext`, and is unaware of the MVC/API constructs. Filters are part of the MVC/API action execution pipeline and have access to rich context like action arguments and results. Use middleware for broad concerns (logging, static files) and filters for API-specific logic (action-level validation, result modification).
16. Global Error Handling (`IExceptionHandler`)
The `IExceptionHandler` interface, introduced in .NET 8, is the recommended way to implement a centralized exception handling strategy. You create a handler class, register it as a service, and it will catch all unhandled exceptions, allowing you to log them and return a consistent, structured error response.
17. Authentication Middleware
Authentication is configured as a service (e.g., `builder.Services.AddAuthentication().AddJwtBearer(...)`) and then enabled in the pipeline with `app.UseAuthentication()`. This middleware is responsible for inspecting the request (e.g., for a JWT in the `Authorization` header), validating the credential, and creating a `ClaimsPrincipal` representing the user.
18. Authorization (Roles & Policies)
Authorization is the process of determining if an identified user has permission to perform an action. ASP.NET Core has a rich, policy-based system. A policy is a set of requirements (e.g., must be in the "Admin" role, must have a "CanDelete" claim) that can be applied to endpoints using the `[Authorize]` attribute.
19. CORS Policy Configuration
CORS is configured as a service where you can define one or more named policies. For example, you can have a lenient policy for development and a very strict policy for production that only allows specific origins, headers, and methods. The policy is then applied in the middleware pipeline using `app.UseCors("PolicyName")`.
20. Health Checks
The Health Checks service provides a dedicated HTTP endpoint (e.g., `/health`) that monitoring systems can use to verify the status of your application. You can configure it to check dependencies like databases, message queues, and other APIs, providing a comprehensive view of your system's health.
21. Logging (`ILogger` & Providers)
The built-in logging framework is a flexible, provider-based system. You inject `ILogger
22. API Versioning
Versioning is handled by the `Asp.Versioning.Mvc` library. It provides a rich set of features for versioning APIs via URL path, query string, or request header, and integrates with Swagger/OpenAPI to generate version-aware documentation.
23. Asynchronous Streaming (`IAsyncEnumerable`)
For endpoints that return large collections of data, you can return `IAsyncEnumerable
24. Rate Limiting Middleware
Introduced in .NET 7, this built-in middleware is essential for protecting your API from overuse. You can configure various rate limiting algorithms, such as fixed window, sliding window, or token bucket, and apply them globally or to specific endpoints to enforce usage quotas.
25. Output Caching Middleware
Introduced in .NET 7, output caching is a high-performance caching middleware that stores entire responses in memory. It's more powerful than response caching because it can serve cached responses without ever touching the MVC/API pipeline, making it extremely fast for frequently accessed, non-personalized data.
In-Depth Core Differences
This section provides a detailed breakdown of the fundamental architectural and philosophical differences between the two frameworks, crucial for developers migrating to ASP.NET Core.
1. Hosting Model & Platform Independence
ASP.NET Framework
Is exclusively Windows-based and tightly coupled to IIS. The application lifecycle is managed by IIS, which loads the .NET Framework runtime into its worker process (`w3wp.exe`). This model is powerful but inflexible and platform-locked.
ASP.NET Core
Is designed for platform independence. It runs as a self-contained console application with its own embedded web server, Kestrel. This allows the exact same application to be deployed on Windows, macOS, or Linux (often in a Docker container) without any changes. While it can be hosted behind IIS, IIS acts as a reverse proxy, not as the application host itself.
2. Request Pipeline: Modules/Handlers vs. Middleware
ASP.NET Framework
Uses a complex, event-based pipeline with `HttpModules` and `HttpHandlers` configured in `Web.config`. The pipeline is opaque and has significant overhead. Web API has its own sub-pipeline with `DelegatingHandler`s that runs within this larger structure.
ASP.NET Core
Features a linear, composable pipeline of **Middleware**. Each piece of middleware is a C# class or delegate that you explicitly add in `Program.cs`. It directly processes the `HttpContext` and can either pass the request to the next component or short-circuit it. This model is transparent, lightweight, and highly performant.
3. Dependency Injection: Add-on vs. First-Class Citizen
ASP.NET Framework
Has no built-in container for dependency injection. To use DI, you must choose, install, and configure a third-party IoC container like Autofac or Unity. This requires creating a custom `IDependencyResolver` to bridge the gap between the container and the framework.
ASP.NET Core
Dependency injection is a core architectural principle, built into the framework from the ground up. Services are registered in the `IServiceCollection` in `Program.cs` and automatically injected wherever they are needed. This promotes better architecture and testability out of the box.
4. Configuration Management
ASP.NET Framework
Configuration is monolithic and based on the XML `Web.config` file. Accessing settings is done via the static `ConfigurationManager` class, which can be difficult to mock for testing and is not easily extensible.
ASP.NET Core
Uses a flexible, provider-based model. It can read configuration from multiple sources like `appsettings.json`, environment variables, user secrets, and command-line arguments. The configuration is available through DI via `IConfiguration`, promoting testability and adherence to the Options Pattern.
5. Project File Format (`.csproj`)
ASP.NET Framework
Uses verbose, non-SDK style `.csproj` files where every single file in the project must be explicitly listed. This makes the project files large and prone to merge conflicts. It also relies on a separate `packages.config` file for NuGet references.
ASP.NET Core
Uses clean, minimal, SDK-style `.csproj` files. The project file only needs to define the target framework and package references. The SDK automatically includes all `.cs` files in the directory tree, making the file much smaller and easier to manage. NuGet references use the `
6. `HttpContext`: Static vs. Injectable
ASP.NET Framework
Relies on the static `HttpContext.Current` to access request information. While convenient, this creates a tight coupling to the web context, making it very difficult to unit test business logic that depends on it.
ASP.NET Core
The `HttpContext` is no longer a static singleton. It is passed through the pipeline and is accessible in controllers directly. For access in other services, you should inject the `IHttpContextAccessor` interface, which allows for clean, testable code that is decoupled from the web context.
7. MVC & Web API Unification
ASP.NET Framework
ASP.NET MVC and ASP.NET Web API were two separate frameworks with different pipelines, base classes (`Controller` vs. `ApiController`), and routing systems. This led to code duplication and confusion.
ASP.NET Core
MVC and Web API have been unified into a single framework. Both API controllers (inheriting from `ControllerBase`) and MVC controllers (inheriting from `Controller`) share the same routing system, filter pipeline, and model binding infrastructure, creating a consistent development experience.
8. In-Depth CORS Configuration
ASP.NET Framework
CORS is an add-on feature requiring the `Microsoft.AspNet.WebApi.Cors` NuGet package. Configuration is typically done in `WebApiConfig.cs` and applied via the `[EnableCors]` attribute. While functional, it lacks the flexibility of named policies.
Scenario: A public API that needs to be accessible from any domain for GET requests.
ASP.NET Core
CORS is a built-in middleware. The recommended approach is to define strongly-named policies in `Program.cs`. This allows you to create different rules for different scenarios (e.g., a lenient policy for development, a strict one for production) and apply them where needed.
Scenario: An API at `api.my-app.com` that must only accept requests from its web frontend at `www.my-app.com`.
Advanced .NET Core Topics
In-depth examples for senior-level interview preparation.
Advanced Authorization with Policies
Policy-based authorization decouples authorization logic from roles. Here's how to create a custom requirement that a user must be a certain age to access an endpoint.
Performance: Distributed Caching with Redis
For multi-server deployments, an in-memory cache is insufficient. A distributed cache like Redis provides a shared cache for all instances of your application.
Integration Testing with WebApplicationFactory
`WebApplicationFactory` from `Microsoft.AspNetCore.Mvc.Testing` bootstraps your app in-memory, allowing you to write tests that make real HTTP requests to your endpoints without hitting the network.
Real-time & gRPC
ASP.NET Core excels at more than just REST APIs. It has first-class support for real-time communication with SignalR and high-performance RPC with gRPC.
SignalR Hub Example
gRPC Service Example
Minimal APIs In-Depth with Route Groups
For larger applications using Minimal APIs, Route Groups are essential for organization. They allow you to group related endpoints under a common prefix and apply filters or other configurations to the entire group.
Structured Logging with Serilog
Structured logging writes log events as key-value pairs (often in JSON) instead of plain text. This makes logs machine-readable and easy to query, filter, and analyze in tools like Seq, Datadog, or Elasticsearch.
API Gateway Pattern with YARP
In a microservices architecture, an API Gateway provides a single entry point for all clients. It can handle routing, authentication, rate limiting, and request aggregation. YARP (Yet Another Reverse Proxy) is a highly customizable gateway toolkit from Microsoft.
Background Tasks with Hosted Services
`IHostedService` provides a clean way to run long-running background tasks that start and stop with your application, such as polling a database, processing a message queue, or performing periodic cleanup.
Architectural Concepts
Foundational principles for designing robust and maintainable APIs.
RESTful Principles
- Client-Server: Enforces separation of concerns. The UI is independent of data storage.
- Stateless: Each request must contain all necessary information. The server holds no client state.
- Cacheable: Responses must define themselves as cacheable or not to improve performance.
- Uniform Interface: A consistent way to interact with resources (URIs, HTTP Verbs, HATEOAS).
- Layered System: Intermediaries (proxies, gateways) can exist without the client's knowledge.
SOLID Principles
- S - Single Responsibility: A class or method should have only one reason to change.
- O - Open/Closed: Software entities should be open for extension, but closed for modification.
- L - Liskov Substitution: Subtypes must be substitutable for their base types.
- I - Interface Segregation: Clients should not be forced to depend on interfaces they do not use.
- D - Dependency Inversion: Depend upon abstractions, not concretions.
Microservices vs. Monolith
This is a fundamental choice in application design. A **monolith** is a single, unified application where all functionality is managed in one codebase and deployed as a single unit. In contrast, a **microservices** architecture breaks the application down into a collection of small, independent services, each responsible for a specific business capability.
Monolith - Pros & Cons
- Simpler to develop, debug, and deploy initially.
- Easier to manage transactions and data consistency.
- Becomes complex and hard to maintain as it grows.
- Scaling requires scaling the entire application.
- A single point of failure; a bug can bring down the whole app.
Microservices - Pros & Cons
- Services can be scaled independently.
- Allows for technology diversity (different languages/databases).
- Enables smaller, autonomous teams to own services.
- Adds significant operational complexity (deployment, monitoring).
- Distributed transactions and data consistency are challenging.
Clean Architecture (Onion Architecture)
A software design philosophy that separates the elements of a design into concentric layers. The core principle is the **Dependency Rule**: source code dependencies can only point inwards. Nothing in an inner layer can know anything at all about something in an outer layer.
- Entities: Core business objects, containing enterprise-wide business rules. They are the least likely to change when external factors change.
- Use Cases: Application-specific business rules. They orchestrate the flow of data to and from the entities.
- Interface Adapters: A set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web.
- Frameworks & Drivers: The outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework, etc.
posted by Lokesh @ July 21, 2025
0 Comments