Q1. What is the MVC Pattern? Explain the roles of Model, View, and Controller.
MVC (Model-View-Controller) is an architectural pattern that separates an application into three interconnected components. The Model represents the application's data and business logic, encapsulating domain logic and data validation. The View is the presentation layer that displays data to users, typically using HTML and CSS. The Controller handles user input, processes requests, interacts with the Model to retrieve or update data, and selects the appropriate View for displaying results. This separation of concerns makes applications more maintainable, testable, and scalable. Each component can be developed and tested independently. The MVC pattern promotes a clean architecture where business logic is separate from presentation, making code reuse and changes easier to implement. ASP.NET MVC implements this pattern through controllers, action methods, views, and models.
Q2. Explain the ASP.NET MVC Request Lifecycle. What happens from the time a user makes a request to the response?
The ASP.NET MVC request lifecycle involves several key steps: (1) A user makes an HTTP request which is received by the ASP.NET runtime; (2) The routing engine matches the URL to a route defined in the RouteConfig and determines the controller and action; (3) The routing engine creates an instance of the appropriate controller and invokes the specified action method; (4) The action method processes the request, which may involve querying a Model and retrieving data; (5) The action method returns a result (typically a ViewResult, JsonResult, etc.); (6) If a ViewResult is returned, the view engine finds the appropriate Razor view file and renders it by passing the model data; (7) The rendered HTML is sent back to the user's browser. This entire process occurs for each HTTP request, allowing the framework to handle multiple concurrent requests.
Example:
public class ProductController : Controller
{
// When user requests /Product/Details/5
public ActionResult Details(int id)
{
// 1. Process request - retrieve data
Product product = GetProductFromDatabase(id);
// 2. Return ViewResult with model
return View(product); // View engine renders Product details view
}
private Product GetProductFromDatabase(int id)
{
// Database query logic
return new Product { Id = id, Name = "Sample Product" };
}
}
Q3. What is Routing in ASP.NET MVC? Explain attribute-based and convention-based routing.
Routing maps URLs to controller actions, determining which controller and action method should handle a request. Convention-based routing uses patterns defined in RouteConfig.cs where routes follow a standard pattern like {controller}/{action}/{id}. The framework infers controller and action names from the URL segments. Attribute-based routing uses [Route] attributes directly on controller classes and action methods to specify routes explicitly. Attribute-based routing provides more flexibility and is easier to understand as the route definition is near the action it controls. In ASP.NET Core, attribute-based routing is the default approach. Routing is crucial for creating user-friendly URLs, SEO optimization, and API versioning. Both approaches can coexist in an application.
Q4. What is a Controller? What are Action Methods?
A Controller is a class that inherits from the Controller base class and handles user requests. It contains action methods that process requests and return responses. Action methods are public methods in a controller class that are called in response to a URL request. Each action method typically: (1) receives request data as parameters; (2) processes the request using business logic; (3) retrieves or updates data using Models; (4) returns an ActionResult (View, Json, Redirect, etc.). Action methods receive parameters from the query string, form data, or route data automatically through model binding. Controllers are the central hub of the MVC application, orchestrating the interaction between Models and Views. Keeping controllers thin by moving business logic to Models or service classes is a best practice.
Q5. What are ActionResult types? Name different ActionResult types.
ActionResult is the base class for all action method return types in MVC. Common ActionResult types include: (1) ViewResult - renders a Razor view with model data; (2) JsonResult - returns JSON-formatted data; (3) RedirectResult - redirects to another URL; (4) RedirectToRouteResult - redirects to another action; (5) ContentResult - returns plain text or custom content; (6) FileResult - returns a file for download; (7) HttpStatusCodeResult - returns HTTP status codes like 404 or 500; (8) PartialViewResult - renders a partial view; (9) EmptyResult - returns nothing. Helper methods like View(), Json(), Redirect(), Content() simplify creating specific ActionResult types. Returning appropriate ActionResult types ensures correct handling of responses and proper HTTP semantics.
Q6. What are Filters in ASP.NET MVC? Explain different types of filters.
Filters allow you to execute custom logic before or after action methods and results are processed. There are four types of filters: (1) Authorization Filters (IAuthorizationFilter) - determine if the user is authorized to execute the action; used for authentication and authorization; (2) Action Filters (IActionFilter) - execute code before and after action method execution; useful for logging, caching, or modifying request data; (3) Result Filters (IResultFilter) - execute code before and after result processing; useful for modifying output or logging responses; (4) Exception Filters (IExceptionFilter) - handle exceptions thrown during action execution; used for error logging and handling. Filters can be applied at the action level, controller level, or globally. Built-in filter attributes like [Authorize], [ActionName], [HttpGet] simplify filter implementation. Filters promote code reusability by extracting cross-cutting concerns from action methods.
Q7. What is Model Binding? How does it work in ASP.NET MVC?
Model binding is the process of mapping HTTP request data (query strings, form data, route parameters, JSON bodies) to action method parameters and complex object properties. The framework automatically converts request data to the appropriate types and populates action method parameters. Model binding uses value providers to locate request data and type converters to convert string data to the target type. For complex types, the binder recursively binds properties by matching parameter names with request data keys. Model binding supports: (1) simple types (int, string, bool, etc.); (2) complex types (classes with properties); (3) collections (arrays, lists, dictionaries); (4) custom model binders for special types. Model binding eliminates the need to manually parse request data, reducing boilerplate code. You can customize model binding using [Bind], [ModelBinder] attributes or creating custom model binders.
Q8. What is ViewBag, ViewData, and TempData? What are the differences?
ViewBag, ViewData, and TempData are mechanisms to pass data from controllers to views: (1) ViewBag is a dynamic object (uses reflection) that allows you to set and access properties using dot notation. It's converted from ViewData internally and is useful for passing small amounts of data; (2) ViewData is a dictionary that passes data using string keys. It requires casting when accessing values and is accessible within the current request only; (3) TempData is a dictionary that persists data across one redirect. It's useful for passing data after a redirect and is automatically cleared after being read. Key differences: ViewBag/ViewData are request-scoped, while TempData survives redirects. ViewBag has dynamic access while ViewData requires casting. Modern practice favors passing strongly-typed models to views instead of using these mechanisms, reserving them for cross-cutting concerns.
Example:
public class StudentController : Controller
{
public ActionResult Index()
{
// Using ViewBag (dynamic)
ViewBag.Title = "Student List";
// Using ViewData (dictionary)
ViewData["Count"] = 10;
// Using TempData (survives redirect)
TempData["SuccessMessage"] = "Student created successfully";
return View();
}
// In View
// @ViewBag.Title // Dynamic access
// @ViewData["Count"] // Dictionary access
// @TempData["SuccessMessage"] // Survives redirect
}
Q9. What is a View? What is Razor syntax?
A View is the presentation layer of the MVC architecture, responsible for rendering HTML to display data to users. Views use Razor syntax, a templating language that combines HTML with C# code. Razor uses the @ symbol to transition between HTML and C# code. Key Razor features include: (1) @ prefix for C# expressions - @Model.PropertyName; (2) @{ } blocks for C# statements; (3) @if, @for, @foreach for control structures; (4) @Html, @Url, @Ajax helpers for generating HTML; (5) Model binding using @Model. Razor is type-safe and provides IntelliSense support in Visual Studio. Views should contain minimal logic - they primarily display data from the Model. Using Razor simplifies view creation and makes templates more readable than traditional ASP.NET server controls.
Q10. What is a Strongly-Typed View? What are advantages over Weakly-Typed Views?
A strongly-typed view explicitly declares the Model type using the @model directive, providing type safety and IntelliSense support. The view knows the Model's shape at compile-time. A weakly-typed view doesn't declare a Model type and accesses data through dynamic ViewBag/ViewData, losing type checking. Advantages of strongly-typed views: (1) compile-time type checking catches errors early; (2) IntelliSense and code completion work correctly; (3) refactoring is safer as the compiler catches broken property references; (4) code is more maintainable and self-documenting. Weakly-typed views are flexible but error-prone as property names are strings and no validation occurs until runtime. Modern practice always uses strongly-typed views with View Models. This ensures type safety, improves developer productivity, and reduces runtime errors.
Q11. What are Data Annotations? How are they used for validation?
Data Annotations are attributes from System.ComponentModel.DataAnnotations namespace used to add metadata to model properties for validation and formatting. Common data annotations include: (1) [Required] - property must have a value; (2) [StringLength(50)] - string must not exceed specified length; (3) [Range(1, 100)] - numeric value must be within range; (4) [EmailAddress] - value must be a valid email; (5) [RegularExpression] - value must match a regex pattern; (6) [Display(Name = "Full Name")] - sets display name for UI; (7) [DataType(DataType.Password)] - specifies data type for rendering. Validation occurs on the client (JavaScript) and server (C# code). Data annotations reduce code duplication by centralizing validation rules in the Model. ASP.NET MVC automatically generates validation messages and client-side validation scripts. Data annotations are also used by Entity Framework for database schema generation.
Q12. What is FluentValidation? How does it differ from Data Annotations?
FluentValidation is an alternative validation framework that allows you to define validation rules using a fluent API in separate validator classes. Instead of decorating model properties with attributes, you create validator classes that inherit from AbstractValidator<T> and define rules in the constructor. Advantages of FluentValidation over Data Annotations: (1) validation logic is separated from the Model, keeping domain models clean; (2) rules can be complex and conditional, adapting based on context; (3) reusable validators across different models; (4) better for cross-property validation; (5) easier to maintain and test validation logic. FluentValidation integrates seamlessly with ASP.NET MVC and provides sophisticated validation scenarios. For simple, straightforward validation, Data Annotations are convenient. For complex validation logic and enterprise applications, FluentValidation is often preferred.
Q13. What is Model State? How do you validate it?
ModelState is a dictionary that contains the state of the Model after model binding and validation. It tracks validation errors and the values of each property. ModelState.IsValid returns true if all properties are valid and contains no errors. When model binding occurs, the framework validates the Model using Data Annotations and adds any errors to ModelState. In action methods, you should check ModelState.IsValid before processing form submissions. If ModelState is invalid, you typically return the view with the same Model so validation errors are displayed to the user. ModelState.AddModelError allows you to add custom validation errors. You can also clear ModelState or individual property errors using ModelState.Clear() or ModelState.Remove(). Checking ModelState.IsValid is crucial for preventing invalid data from being processed or saved to the database.
Q14. What is Dependency Injection (DI)? Why is it important in ASP.NET Core?
Dependency Injection is a design pattern where objects receive their dependencies from external sources rather than creating them internally. Instead of a class creating dependencies it needs, those dependencies are "injected" through constructors, properties, or method parameters. DI promotes loose coupling, testability, and maintainability. ASP.NET Core has built-in DI support through the IServiceProvider and IServiceCollection. Dependencies are registered in the Startup.cs (or Program.cs in minimal hosting model) ConfigureServices method, and the framework automatically injects registered services into constructors. Benefits include: (1) easier unit testing by injecting mock implementations; (2) loose coupling between classes; (3) centralized dependency management; (4) simplified configuration management. ASP.NET Core's DI container supports three lifetimes: (1) Transient - new instance created every time; (2) Scoped - one instance per request; (3) Singleton - one instance for application lifetime.
Example:
public interface IEmailService
{
void SendEmail(string to, string subject, string body);
}
public class EmailService : IEmailService
{
public void SendEmail(string to, string subject, string body)
{
// Email sending logic
}
}
// In Startup.cs ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IEmailService, EmailService>();
}
// In Controller - DI injects EmailService
public class UserController : Controller
{
private readonly IEmailService _emailService;
public UserController(IEmailService emailService)
{
_emailService = emailService;
}
public ActionResult Register(User user)
{
_emailService.SendEmail(user.Email, "Welcome", "...");
return View();
}
}
Q15. What is the difference between AddSingleton, AddScoped, and AddTransient?
These are the three DI lifetimes in ASP.NET Core: (1) AddSingleton - creates one instance for the entire application lifetime. All requests share the same instance. Use for stateless services and factories; (2) AddScoped - creates one instance per HTTP request. Within a request, the same instance is shared. Use for DbContext and request-scoped services; (3) AddTransient - creates a new instance every time the service is requested. Use for lightweight, stateless services. Choosing the correct lifetime is crucial for memory management and correct behavior. Singleton instances must be thread-safe as they're shared. Scoped is the safest default for most services, especially Entity Framework DbContext. Transient is useful for services without state where instantiation cost is low.
Q16. What is Middleware in ASP.NET Core? Explain the middleware pipeline.
Middleware is software that handles HTTP requests and responses in ASP.NET Core. Middleware components form a pipeline where each component can process a request, pass it to the next component, and process the response on the way back. Middleware is registered in the Configure method of Startup.cs and executes in order. Key points about middleware: (1) it processes requests and responses in both directions; (2) order of registration matters - middleware executes in the order registered; (3) any middleware can short-circuit the pipeline by not calling next.Invoke(); (4) built-in middleware includes routing, authentication, authorization, CORS, logging; (5) custom middleware can be created for application-specific needs. The middleware pipeline is crucial for implementing cross-cutting concerns like logging, error handling, authentication, and security headers. Understanding middleware is essential for ASP.NET Core development.
Q17. What is IServiceCollection? How do you register services?
IServiceCollection is an interface that represents the collection of service descriptors for dependency injection. It's used in the ConfigureServices method to register services (dependencies) that will be injected throughout the application. Services are registered using extension methods: (1) AddScoped<IService, Service>() - registers an interface/implementation pair; (2) AddSingleton<IService>(new Service()) - registers a pre-created instance; (3) AddTransient<Service>() - registers a concrete type without interface; (4) AddSingleton(typeof(IService), typeof(Service)) - non-generic registration. Services can also be registered with factory functions: services.AddScoped<IService>(sp => new Service(dependency)). ASP.NET Core automatically registers many built-in services like logging, configuration, and options. Proper service registration enables DI, improves testability, and promotes loose coupling throughout the application.
Q18. What is .NET Core? How does it differ from .NET Framework?
.NET Core is a modern, open-source, cross-platform implementation of .NET that runs on Windows, Linux, and macOS. Key differences from .NET Framework: (1) .NET Core is cross-platform, .NET Framework is Windows-only; (2) .NET Core is modular and lightweight, .NET Framework includes many built-in components; (3) .NET Core uses dependency injection natively, .NET Framework requires third-party containers; (4) ASP.NET Core is the web framework for .NET Core, ASP.NET MVC 5 and Web API target .NET Framework; (5) .NET Core is open-source on GitHub, .NET Framework is proprietary; (6) .NET Core is containerization-friendly due to smaller footprint; (7) .NET 5 unified .NET Core and .NET Framework, subsequent versions (.NET 6, 7, 8) continue this unified platform. For new projects, .NET Core (or later unified .NET versions) is recommended over .NET Framework which is in maintenance mode.
Q19. What is Program.cs in ASP.NET Core? Explain the Startup process.
Program.cs is the entry point of an ASP.NET Core application. It creates and configures the WebHostBuilder (or WebApplicationBuilder in newer versions), which sets up the application host, dependency injection, and middleware pipeline. The typical startup process: (1) Program.Main() is called; (2) a WebHost is created and configured; (3) ConfigureServices is called to register dependencies in the DI container; (4) Configure is called to set up the middleware pipeline; (5) the WebHost is built and run; (6) the application starts listening for HTTP requests. In modern ASP.NET Core, the Startup class can be replaced with minimal hosting model where configuration is done directly in Program.cs. ConfigureServices registers services needed throughout the application. Configure sets up middleware handling requests and responses.
Q20. What is Configuration in ASP.NET Core? How do you read settings from appsettings.json?
Configuration in ASP.NET Core is managed through the IConfiguration interface, which provides access to application settings from various sources including appsettings.json, environment variables, and command-line arguments. The configuration system is hierarchical and supports multiple sources with precedence rules. To read settings: (1) inject IConfiguration into controllers or services; (2) access values using configuration["key"] syntax or strongly-typed options. appsettings.json contains application settings in JSON format, typically including database connections, logging settings, and custom application settings. ASP.NET Core supports environment-specific configuration files like appsettings.Development.json. Options pattern allows you to define strongly-typed configuration classes and inject them, providing better type safety. Configuration values can be overridden by environment variables or command-line arguments, enabling deployment-specific settings without code changes. Secrets management handles sensitive information like API keys separately from configuration files.
Example:
// appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyDb;Trusted_Connection=true;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
// Reading configuration
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration configuration)
{
_configuration = configuration;
}
public ActionResult Index()
{
string connString = _configuration["ConnectionStrings:DefaultConnection"];
return View();
}
}
Q21. What is Secrets Management in ASP.NET Core? How do you store sensitive data?
Secrets Management refers to safely storing sensitive information like API keys, connection strings, and passwords outside of source code and configuration files. In development, ASP.NET Core uses the Secret Manager tool which stores secrets in a JSON file outside the project directory, excluded from version control. To use the Secret Manager: (1) run `dotnet user-secrets init` in the project; (2) run `dotnet user-secrets set "key" "value"` to store secrets; (3) access secrets through IConfiguration like regular settings. In production, use external secret management systems like Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault. These services provide encryption, audit trails, and rotation capabilities. Secrets should never be hardcoded in source code or stored in appsettings.json. Environment variables can also store secrets but external vaults are more secure and manageable at scale. Proper secrets management is critical for application security.
Q22. What is Authentication and Authorization? How do they differ?
Authentication is the process of verifying a user's identity - confirming that the user is who they claim to be. Authorization is the process of determining what authenticated users are allowed to do - what resources they can access. Authentication answers "Who are you?" while authorization answers "What can you do?". In ASP.NET Core, authentication is implemented using schemes (like Cookies, JWT, OAuth) configured in ConfigureServices and middleware. Authorization uses policies and roles defined in Startup and applied to actions using [Authorize] attributes. Common authentication schemes include: (1) Cookie-based - traditional form authentication; (2) JWT - token-based for APIs and SPAs; (3) OAuth - third-party authentication; (4) OpenID Connect - for SSO. Authorization can be role-based (user belongs to a role) or claim-based (user has specific claims). Both authentication and authorization are essential for securing web applications and APIs.
Q23. What is JWT (JSON Web Token)? How is it used for authentication?
JWT (JSON Web Token) is a token-based authentication mechanism for APIs and SPAs. A JWT consists of three parts separated by dots: (1) Header - specifies token type and algorithm; (2) Payload - contains claims (user data); (3) Signature - ensures token integrity and is signed using a secret key. When a user logs in, the server creates a JWT and returns it to the client. The client includes the JWT in the Authorization header of subsequent requests. The server validates the JWT signature to ensure it hasn't been tampered with. JWTs are stateless - the server doesn't need to store session data, making them ideal for distributed systems and microservices. Tokens have an expiration time (exp claim) for security. Refresh tokens are often used to obtain new access tokens when they expire. JWTs are widely used for securing REST APIs and mobile applications.
Q24. What are Claims? How are they used in authorization?
Claims are pieces of information about a user represented as key-value pairs. Examples include user ID, email, roles, and custom attributes. Claims are embedded in authentication tokens (JWT) or stored in session data. The ClaimsPrincipal represents an authenticated user with their claims. Claims-based authorization is more flexible than role-based as it allows granular control. You can define policies that check for specific claims: [Authorize(Policy = "CanEditArticles")]. Claims allow implementing complex authorization scenarios like: (1) permission-based access; (2) attribute-based access control; (3) time-based restrictions. Policies are defined in Startup.cs using AddAuthorizationPolicies(). Claims-based authorization scales better than hardcoded role checks in large applications. Understanding and properly implementing claims-based authorization is important for building secure, flexible systems.
Q25. What is the [Authorize] attribute? How do you implement authorization policies?
The [Authorize] attribute restricts access to action methods, controllers, or pages to authenticated users. You can specify roles or policies: [Authorize(Roles = "Admin")] or [Authorize(Policy = "CanEdit")]. Without arguments, [Authorize] requires any authenticated user. Authorization policies are defined in Startup.cs using services.AddAuthorizationPolicies where you specify requirements for access. Policies can check claims, roles, or custom logic. Multiple attributes can be combined - the most restrictive applies. [AllowAnonymous] allows access to specific actions even when authorization is required at the controller level. Authorization is enforced by the AuthorizationMiddleware. Understanding authorization attributes and policies is essential for securing web applications and APIs properly.
Example:
// In Startup.cs ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("CanEdit", policy =>
policy.RequireClaim("EditPermission", "true"));
});
}
// Using [Authorize] with policy
public class ArticleController : Controller
{
[Authorize(Policy = "CanEdit")]
public ActionResult Edit(int id)
{
return View();
}
[Authorize(Roles = "Admin")]
public ActionResult Delete(int id)
{
return View();
}
}
Q26. What is Entity Framework Core? How does it relate to ASP.NET Core?
Entity Framework Core (EF Core) is an Object-Relational Mapping (ORM) framework that allows you to work with databases using .NET objects instead of writing SQL. It abstracts database operations, making data access code more maintainable and testable. EF Core is the recommended data access technology for ASP.NET Core applications. Key features include: (1) DbContext - represents a session with the database; (2) DbSet - represents a collection of entities; (3) LINQ queries - type-safe queries; (4) change tracking - automatic tracking of entity changes; (5) migrations - version control for database schema; (6) lazy loading - automatic loading of related data. EF Core supports multiple databases (SQL Server, PostgreSQL, SQLite, etc.). It integrates with dependency injection, allowing you to inject DbContext into controllers and services. Using EF Core reduces boilerplate SQL code and provides type safety, improving productivity and code quality.
Q27. What is DbContext? How do you configure it in ASP.NET Core?
DbContext is the main class in Entity Framework Core that manages entity objects and interactions with the database. It represents a unit of work - a session during which entities can be queried, added, modified, or deleted. DbContext tracks changes to entities and generates appropriate SQL commands. To configure DbContext: (1) create a class inheriting from DbContext; (2) define DbSet properties for each entity; (3) override OnConfiguring or use ConfigureServices to register it with DI. DbContext should typically be registered as scoped (one per request). DbContext implements IDisposable and should be disposed after use to release database connections. Key methods include: (1) SaveChanges() - persists changes to database; (2) Add(), Update(), Remove() - change tracking; (3) Entry() - access change tracking info; (4) Database.Migrate() - apply pending migrations. Proper DbContext usage is crucial for data access in ASP.NET Core applications.
Q28. What are Entity Framework Migrations? How do you create and apply them?
Migrations allow you to version-control database schema changes. When your entity models change, migrations generate SQL scripts that update the database schema accordingly. To create a migration: (1) run `dotnet ef migrations add MigrationName`; (2) this creates a migration file with Up() and Down() methods; (3) Up() contains changes to apply, Down() contains changes to undo. To apply migrations: (1) run `dotnet ef database update`; (2) this executes pending migrations against the database. Migrations track which migrations have been applied, preventing duplicate execution. You can rollback to previous migrations using `dotnet ef database update PreviousMigration`. Migrations are essential for maintaining database consistency across environments and teams. They provide a declarative approach to schema management, eliminating manual SQL scripts.
Q29. What is the difference between Eager Loading, Lazy Loading, and Explicit Loading in EF Core?
These are techniques for loading related data in Entity Framework Core: (1) Eager Loading - loads related entities when the main entity is retrieved using Include(). Multiple queries are combined into a single database query. Use when you know you'll need related data immediately; (2) Lazy Loading - related entities are automatically loaded when accessed for the first time. Requires virtual navigation properties and lazy loading proxy package. Can cause N+1 query problems if not careful; (3) Explicit Loading - uses Load() or LoadAsync() to manually load related entities on demand. Gives explicit control over when related data is loaded. Choose based on your needs: eager loading for better performance when related data is known to be needed, lazy loading for convenience (with caveats), and explicit loading for fine-grained control. Be aware of N+1 query problems - querying related data in loops causes excessive database queries.
Q30. What are the differences between Code-First and Database-First approaches in EF Core?
Code-First and Database-First are two approaches to using Entity Framework Core: (1) Code-First - you define entity classes and DbContext in code, then create the database from those models. Migrations generate SQL. This approach keeps code at the center and works well for greenfield projects. You control the schema through code changes; (2) Database-First - you start with an existing database, then generate entity classes and DbContext from it using scaffolding (`dotnet ef dbcontext scaffold`). This approach works well for legacy systems. Updates to the database require re-scaffolding. Code-First is generally preferred for new ASP.NET Core projects as it keeps code and data model in sync more easily. Database-First is useful when integrating with existing databases. Hybrid approaches are also possible where you maintain both code and database carefully.
Q31. What is CORS? How do you enable CORS in ASP.NET Core?
CORS (Cross-Origin Resource Sharing) is a security feature that controls which origins (domains) can access your web API. By default, browsers restrict requests from web pages to APIs on different origins. Enabling CORS allows controlled cross-origin access. To enable CORS in ASP.NET Core: (1) add CORS services in ConfigureServices: services.AddCors(); (2) configure CORS policies specifying allowed origins, methods, headers, and credentials; (3) add CORS middleware in Configure: app.UseCors("PolicyName"); (4) apply [EnableCors] attribute to controllers or actions. CORS policies can be specific (allow certain origins) or permissive (allow all origins). In production, use restrictive policies. CORS is essential for integrating APIs with web applications, mobile apps, and third-party services. Proper CORS configuration balances accessibility and security.
Q32. What is Content Security Policy (CSP)? Why is it important?
Content Security Policy (CSP) is a security mechanism that restricts what resources (scripts, styles, images, etc.) a web page can load. CSP mitigates cross-site scripting (XSS) attacks by specifying trusted sources for content. CSP is configured through response headers or meta tags. Benefits include: (1) preventing inline script execution unless explicitly allowed; (2) restricting external script sources; (3) preventing image and style loading from untrusted sources; (4) protecting against data exfiltration. In ASP.NET Core, CSP headers can be set in middleware or using security libraries. A strict CSP policy significantly reduces XSS vulnerability surface. CSP can be enforced or in report-only mode for testing. Implementing CSP is a security best practice for web applications.
Q33. What is Bundling and Minification? How do they improve application performance?
Bundling combines multiple files (CSS or JavaScript) into a single file, reducing the number of HTTP requests needed to load a page. Minification removes unnecessary characters from code (whitespace, comments) without affecting functionality, reducing file size. These techniques improve performance by: (1) reducing HTTP requests and bandwidth; (2) improving page load times; (3) speeding up application response. In ASP.NET MVC, bundling is configured in BundleConfig.cs. In ASP.NET Core, tools like WebPack or grunt are commonly used. For production builds, Visual Studio automatically minifies CSS and JavaScript. CDNs can serve bundled and minified files from geographically distributed servers. Browser caching further improves performance. Modern web development emphasizes these optimization techniques as they significantly impact user experience and SEO.
Q34. What are Areas in ASP.NET MVC? How do you create and use them?
Areas are a feature that allows you to organize large MVC applications into subsections with their own models, views, and controllers. Each area has a separate folder structure with its own Controllers, Views, and Models folders. Areas are useful for: (1) large applications with distinct functional areas; (2) separating admin functionality from user-facing pages; (3) organizing code by business domain; (4) allowing multiple teams to work on different areas. To create an area: (1) right-click project in Visual Studio and select "Add Area"; (2) enter area name (e.g., "Admin"); (3) Visual Studio creates the folder structure. Routes must be configured for areas using area-specific route registration. Controllers in areas inherit from Controller and don't require special attributes. Views in areas are resolved from the area's Views folder first, then the root Views folder. Areas improve code organization and maintainability in large applications.
Q35. What are Partial Views? How are they useful?
Partial views are reusable view components that contain markup for a portion of a page. They allow you to extract common HTML patterns into separate files, reducing code duplication. Partial views are rendered using Html.Partial() or Html.RenderPartial() helpers. Key benefits: (1) code reuse across multiple views; (2) better organization of complex views; (3) easier maintenance - changes in one place affect all uses; (4) simplifies testing by isolating concerns. Partial views can accept a Model and receive data from the parent view. They are particularly useful for: (1) navigation menus repeated across pages; (2) product cards in listing pages; (3) form validation error displays; (4) pagination controls. Partial views are different from View Components which have their own logic and data handling. For simple markup reuse, partial views are sufficient; for components with complex logic, View Components are more appropriate.
Q36. What are View Components? How are they different from Partial Views?
View Components are self-contained, reusable components with their own logic and data handling. Unlike partial views, View Components can execute logic, fetch data, and have their own view file. To create a View Component: (1) create a class inheriting from ViewComponent; (2) implement Invoke() or InvokeAsync() to retrieve data; (3) return View(model). View Components are invoked using Component.InvokeAsync("ComponentName", parameters). Advantages over partial views: (1) encapsulate logic within the component; (2) independently handle data fetching; (3) can be cached independently; (4) better for complex, reusable functionality; (5) improved testability due to separated logic. Use partial views for simple markup reuse, View Components for reusable functionality with logic. View Components are ideal for: (1) shopping cart display; (2) user profile sidebars; (3) featured products sections; (4) notification widgets. View Components promote better separation of concerns and code reusability in complex applications.
Q37. What are Tag Helpers in ASP.NET Core? How do they improve view development?
Tag Helpers are a feature in Razor templates that render HTML elements using C# code. They provide HTML-like syntax for server-side logic, making views more readable and maintainable. Tag Helpers are prefixed with asp- attribute (e.g., asp-for, asp-controller, asp-action). Built-in Tag Helpers include: (1) Form Tag Helper - manages form submission and CSRF tokens; (2) Input Tag Helper - generates appropriate input elements based on model properties; (3) Select Tag Helper - creates dropdown lists; (4) Anchor Tag Helper - generates links with route parameters; (5) Partial Tag Helper - includes partial views. Benefits: (1) IntelliSense support in views; (2) compile-time validation; (3) cleaner, more readable markup than HTML helpers; (4) automatic CSRF token inclusion in forms; (5) better SEO (URLs are friendlier). Tag Helpers are the recommended approach in ASP.NET Core for dynamic HTML generation, replacing older HTML Helpers from ASP.NET MVC.
Q38. What is Model-View-ViewModel (MVVM) pattern? How does it relate to MVC?
MVVM (Model-View-ViewModel) is a UI architectural pattern that separates the UI (View) from the business logic (ViewModel) more completely than MVC. The ViewModel exposes commands and properties that the View binds to using data binding mechanisms. The Model remains the same as in MVC. MVVM is commonly used in WPF, Xamarin, and JavaScript frameworks like Vue.js and Angular. In the context of ASP.NET Core web applications, the ViewModel concept is related but not identical - ASP.NET views don't have two-way data binding like XAML or frontend frameworks. However, ASP.NET Core uses View Models as DTOs (Data Transfer Objects) to pass data from controllers to views. This is a best practice that aligns with MVVM principles - the ViewModel (in ASP.NET context) is a separate class tailored for view needs rather than using domain models directly.
Example:
// Model - Domain model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
// ViewModel - Tailored for view
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string FormattedPrice { get; set; }
public bool IsAvailable { get; set; }
}
// Controller maps Model to ViewModel
public ActionResult Details(int id)
{
Product product = _repository.GetProduct(id);
var viewModel = new ProductViewModel
{
Id = product.Id,
Name = product.Name,
FormattedPrice = product.Price.ToString("C"),
IsAvailable = product.Stock > 0
};
return View(viewModel);
}
Q39. What is Anti-Forgery Token? How does it protect against CSRF attacks?
An Anti-Forgery Token is a security mechanism that protects against Cross-Site Request Forgery (CSRF) attacks. CSRF attacks occur when a malicious site tricks a user into making unintended requests to another site where the user is authenticated. The anti-forgery token is a unique, unpredictable token generated by the server and included in HTML forms. The form also includes a token in a hidden input or cookie. When the form is submitted, the server verifies that the token matches, ensuring the request originated from the legitimate application. In ASP.NET MVC, you include the token using @Html.AntiForgeryToken() in forms. In ASP.NET Core, Form Tag Helper automatically includes the anti-forgery token. The server validates the token using [ValidateAntiForgeryToken] attribute on action methods. Tokens are unique per user and session, making them effective against CSRF attacks. Proper implementation of anti-forgery tokens is essential for form security.
Q40. What are HTTP Security Headers? Name common security headers.
HTTP Security Headers are response headers that instruct browsers on how to handle security-related concerns. Common security headers include: (1) Strict-Transport-Security (HSTS) - enforces HTTPS; (2) Content-Security-Policy (CSP) - prevents XSS attacks; (3) X-Content-Type-Options - prevents MIME type sniffing; (4) X-Frame-Options - prevents clickjacking; (5) X-XSS-Protection - enables browser XSS filters; (6) Referrer-Policy - controls referrer information sharing; (7) Permissions-Policy - controls browser features. Setting these headers improves application security by leveraging browser protections. In ASP.NET Core, security headers can be added in middleware. Libraries like NWebsec simplify security header management. Configuring security headers is a best practice that requires minimal effort but significantly improves security posture.
Q41. What is MVC Routing? Explain how route matching works.
Routing maps incoming URLs to controller actions. In ASP.NET MVC, routes are defined in RouteConfig.cs with patterns like {controller}/{action}/{id}. When a request arrives, the routing engine matches it against registered routes in order, using the first matching route. Route parameters are extracted from the URL and passed to action methods. For example, /Products/Details/5 matches the pattern, extracting controller="Products", action="Details", id="5". Default values provide fallback values if URL segments are missing. Route constraints limit what values are matched (e.g., id must be numeric). Attribute-based routing in ASP.NET Core uses [Route] attributes on controllers and actions for more explicit route definition. Understanding routing is essential for creating user-friendly URLs, API design, and implementing URL-based features like SEO-friendly slugs.
Q42. What is Model Validation? How do you perform server-side validation?
Model validation ensures that data meets specified criteria before processing. Server-side validation occurs on the server, checking ModelState.IsValid in action methods. If invalid, the view is returned with validation errors displayed. Validation rules are defined using Data Annotations on model properties or through FluentValidation. Server-side validation is essential for security since client-side validation can be bypassed. Always validate on the server before processing user input. ModelState contains validation errors that can be displayed in views using Html.ValidationMessageFor. Custom validation logic can be implemented in action methods or by creating custom validation attributes. Proper validation prevents invalid data from reaching the database and improves user experience by providing clear error messages.
Q43. What is Caching in ASP.NET Core? Explain different types of caching.
Caching stores frequently accessed data in memory to improve performance. ASP.NET Core supports several caching mechanisms: (1) In-Memory Caching - stores data in the application's memory using IMemoryCache; (2) Distributed Caching - stores data in an external store (Redis, SQL Server) accessible across multiple servers, using IDistributedCache; (3) Response Caching - caches HTTP responses using cache headers; (4) Output Caching - caches rendered HTML of views. In-memory caching is fast but limited to a single server. Distributed caching enables sharing cached data across multiple application instances. Caching improves performance but requires careful management of cache invalidation and coherency. IMemoryCache is registered in DI and injected into controllers/services. Cache TTL (time-to-live) determines how long data remains cached. Proper caching strategy significantly improves application scalability and responsiveness.
Q44. What is Logging in ASP.NET Core? How do you implement structured logging?
Logging records application events, errors, and diagnostic information for debugging and monitoring. ASP.NET Core has built-in logging support through ILogger and ILoggerFactory. Logging is configured in Startup.cs using AddLogging(). Log levels include Debug, Information, Warning, Error, and Critical. Logging providers output logs to various destinations (Console, File, Event Log, etc.). ILogger is injected into controllers and services for logging messages. Structured logging captures log data in a structured format (like JSON) for easier parsing and analysis. Popular structured logging libraries include Serilog, NLog, and log4net. Proper logging is essential for monitoring production applications, troubleshooting issues, and auditing important operations. Logging should balance detail (log enough for debugging) with performance (excessive logging degrades performance).
Example:
public class ProductController : Controller
{
private readonly ILogger<ProductController> _logger;
public ProductController(ILogger<ProductController> logger)
{
_logger = logger;
}
public ActionResult Index()
{
_logger.LogInformation("Listing products");
try
{
var products = GetProducts();
return View(products);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving products");
throw;
}
}
}
Q45. What is Exception Handling Middleware? How do you implement it?
Exception handling middleware catches unhandled exceptions and provides appropriate responses. In ASP.NET Core, you implement it as middleware in the Configure method or using try-catch blocks in other middleware. UseDeveloperExceptionPage() displays detailed error information in development. UseExceptionHandler() handles exceptions in production and can display custom error pages. Middleware processes exceptions before they reach the user. Exception handling middleware typically: (1) logs the exception; (2) returns an appropriate HTTP status code; (3) displays a user-friendly error message. Global exception handling reduces code duplication and ensures consistent error handling. You should also handle exceptions in action methods for specific error scenarios. Proper exception handling is crucial for application stability and user experience.
Q46. What are REST API principles? How do you design a RESTful API?
REST (Representational State Transfer) is an architectural style for building web APIs. Key REST principles: (1) Resources - everything is a resource identified by a URI (/api/products/5); (2) Methods - use HTTP methods correctly (GET for retrieval, POST for creation, PUT/PATCH for updates, DELETE for deletion); (3) Statelessness - each request contains all information needed, no session state; (4) Representations - resources are represented in formats like JSON or XML; (5) HATEOAS - responses include links to related resources. RESTful API design guidelines: (1) use nouns for resources, not verbs (/products not /getProducts); (2) use HTTP status codes correctly (200 OK, 201 Created, 400 Bad Request, 404 Not Found); (3) support filtering, sorting, and pagination for list endpoints; (4) version APIs to manage breaking changes; (5) use authentication and authorization. ASP.NET Core Web API is designed for building RESTful APIs. Following REST principles creates predictable, maintainable, and scalable APIs.
Q47. What is API Versioning? How do you implement it in ASP.NET Core?
API versioning allows you to manage API changes without breaking existing clients. Versioning strategies include: (1) URL versioning - /api/v1/products; (2) Query string versioning - /api/products?version=1; (3) Header versioning - Accept: application/json;v=1; (4) Media type versioning - Accept: application/vnd.api+json;version=1. In ASP.NET Core, you can implement versioning using route attributes, action constraints, or the ApiVersioning NuGet package. Versioning should be planned from the start to avoid confusion. Deprecated API versions should be phased out gradually. Proper documentation indicating which versions are supported helps clients understand compatibility. API versioning is essential in production systems where multiple client versions may be in use simultaneously.
Q48. What is Swagger/OpenAPI? How do you document APIs?
Swagger (now OpenAPI) is a specification for documenting REST APIs. It provides a standard way to describe endpoints, parameters, responses, and authentication methods. Swagger UI generates an interactive documentation interface where developers can test API endpoints directly. In ASP.NET Core, Swashbuckle package integrates Swagger support. To enable Swagger: (1) install Swashbuckle NuGet package; (2) register Swagger in ConfigureServices; (3) add Swagger middleware in Configure. You can document endpoints using XML comments on action methods, which are automatically included in Swagger documentation. Swagger generates an OpenAPI specification file (JSON/YAML) that describes the API. Benefits: (1) auto-generated interactive documentation; (2) API discovery and exploration; (3) client code generation; (4) API testing without external tools. Proper API documentation using Swagger improves API usability and reduces support burden.
Q49. What is Health Checks? How do you implement health checks in ASP.NET Core?
Health checks are mechanisms to verify that an application and its dependencies are functioning correctly. Load balancers and orchestration platforms (Kubernetes) use health checks to determine whether to route traffic to an instance. In ASP.NET Core, health checks are implemented using the Health Checks API. To use health checks: (1) install Microsoft.Extensions.Diagnostics.HealthChecks NuGet package; (2) register health checks in ConfigureServices: services.AddHealthChecks(); (3) map health check endpoint in Configure: endpoints.MapHealthChecks("/health"); (4) implement custom health check classes by implementing IHealthCheck. Health checks can verify: (1) database connectivity; (2) external service availability; (3) file system access; (4) memory/disk usage. Health check responses include status (Healthy, Degraded, Unhealthy) and optional diagnostic information. Proper health checks improve application reliability and enable automated failure detection.
Q50. What is Deployment in ASP.NET Core? Explain different deployment options.
Deployment is the process of moving an application from development to production. ASP.NET Core deployment options include: (1) IIS (Internet Information Services) - traditional Windows hosting; (2) Azure App Service - cloud hosting on Microsoft Azure; (3) Docker Containers - containerized deployment for consistency across environments; (4) Kubernetes - orchestration of containerized applications; (5) Self-hosted on Linux/Windows servers using Kestrel web server; (6) AWS, Google Cloud, DigitalOcean - alternative cloud providers. Deployment considerations: (1) choose appropriate hosting environment; (2) configure application settings for production; (3) set up database migrations and initialization; (4) enable logging and monitoring; (5) implement backup and disaster recovery; (6) use CI/CD pipelines for automated deployment. ASP.NET Core's cross-platform nature and containerization support make deployment flexible and scalable. Proper deployment planning ensures application availability and reliability in production.
Example:
// Dockerfile for containerized deployment
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/runtime:6.0
WORKDIR /app
COPY --from=build /app/out .
EXPOSE 80
ENTRYPOINT ["dotnet", "MyApp.dll"]