1. How do you handle concurrency in a multi-threaded .NET application?
Answer:
Concurrency issues arise when multiple threads access shared resources simultaneously, leading to race conditions. In .NET, you can handle this by:
-
Locks: Using
lockstatements ensures that only one thread can access the critical section at a time. -
Mutex: For multi-process synchronization,
Mutexcan be used. -
Thread-Safe Collections: Using collections like
ConcurrentQueueensures safe access in a multi-threaded environment.
2. How would you manage large data retrieval to avoid performance issues in .NET?
Answer:
To efficiently handle large datasets:
-
Paging: Implement pagination by limiting the number of records fetched using
Skip()andTake()in LINQ queries or SQL queries withLIMITandOFFSET. -
Lazy Loading: In Entity Framework, enable Lazy Loading to only load related data when it’s needed.
-
Asynchronous Operations: Use asynchronous methods (
asyncandawait) to avoid blocking the main thread during data retrieval.
3. What steps would you take to improve the performance of a slow-running SQL query in a .NET application?
Answer:
To optimize slow-running SQL queries:
-
Indexing: Ensure proper indexing on columns that are used frequently in
WHERE,JOIN, andORDER BYclauses. -
Execution Plan: Analyze the query execution plan using SQL tools like
SQL Profilerto identify bottlenecks. -
Caching: Implement caching using tools like Redis or MemoryCache to reduce database hits.
-
EF Core Optimization: If using Entity Framework, ensure that
AsNoTracking()is used for read-only queries to improve performance.
4. How would you implement a logging mechanism in a .NET application?
Answer:
For logging, you can use ILogger in ASP.NET Core:
-
ILogger Interface: Integrate the built-in
ILoggerinterface to log messages at different severity levels (e.g.,Information,Warning,Error). -
Third-Party Libraries: Use NLog, Serilog, or log4net for advanced logging features.
-
Centralized Logging: Use centralized logging systems like ELK Stack or Splunk to collect and analyze logs from different application instances.
5. How do you handle dependency injection in a .NET Core application?
Answer:
.NET Core provides built-in Dependency Injection (DI), which you can leverage to improve code testability and maintainability. Here’s how:
-
Service Registration: Register services in the
Startup.csfile usingservices.AddScoped(),services.AddSingleton(), orservices.AddTransient(). -
Constructor Injection: Inject the required services into your classes through constructors, avoiding tight coupling.
Example:
public class MyController : Controller
{
private readonly IMyService _myService;
public MyController(IMyService myService)
{
_myService = myService;
}
}
6. How do you implement JWT authentication in a .NET application?
Answer:
To implement JWT authentication:
-
Token Generation: Generate a JWT token on successful login using System.IdentityModel.Tokens.Jwt.
-
Token Validation: Use JwtBearer middleware in Startup.cs to validate tokens and protect API endpoints.
Example of generating JWT:
var claims = new[]
{
new Claim(ClaimTypes.Name, username)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secretKey"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "your-issuer",
audience: "your-audience",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
7. How would you implement API versioning in a .NET Core application?
Answer:
To implement API versioning:
-
URL Versioning: Version the API by including the version in the URL, e.g.,
/api/v1/,/api/v2/. -
Header Versioning: You can also version via headers, such as using
Accept: application/vnd.myapi.v1+json. -
Query Parameter Versioning: You can pass the version as a query string parameter, like
/api/products?version=1.
In Startup.cs, configure versioning like so:
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
});
8. How do you implement caching in .NET to improve performance?
Answer:
Caching can significantly reduce the load on your server and database. In .NET:
-
MemoryCache: For in-memory caching, use the
MemoryCacheclass. -
Distributed Caching: For larger-scale applications, use Redis or SQL Server as distributed caches to share cache across multiple instances.
-
Output Caching: In web applications, you can use Response Caching to cache the HTTP response at the server level.
Example:
var cache = new MemoryCache(new MemoryCacheOptions());
cache.Set("key", "value", TimeSpan.FromMinutes(5));
9. How would you handle error handling in a .NET Core Web API?
Answer:
For effective error handling:
-
Use Middleware: Create global error-handling middleware to catch unhandled exceptions and return appropriate HTTP status codes.
-
Custom Error Response: Return a well-structured error message in the response body to help users and developers understand the error.
-
Logging: Log the details of exceptions to track issues and debug them later.
Example:
app.UseExceptionHandler("/error");
app.UseStatusCodePagesWithReExecute("/error/{0}");
10. How would you secure sensitive data like passwords in .NET Core?
Answer:
To secure sensitive data:
-
Hash Passwords: Use bcrypt or PBKDF2 to hash passwords before storing them.
-
Use Encryption: Encrypt sensitive data using algorithms like AES.
-
Environment Variables: Store sensitive keys and passwords in environment variables or a secure configuration store instead of hardcoding them.
Example using ASP.NET Core Identity to hash passwords:
var passwordHasher = new PasswordHasher<ApplicationUser>();
var hashedPassword = passwordHasher.HashPassword(user, plainTextPassword);
11. How would you implement role-based access control (RBAC) in a .NET application?
Answer:
To implement RBAC:
-
Define Roles: Create roles in the database (e.g.,
Admin,User,Manager). -
Assign Permissions: Assign permissions to roles, such as
read,write,delete. -
Authorize Requests: Use [Authorize] attribute in controllers and actions to restrict access based on roles.
Example:
[Authorize(Roles = "Admin")]
public IActionResult AdminDashboard()
{
return View();
}
12. How would you implement file uploads in a .NET Core application?
Answer:
To handle file uploads:
-
Front-End: Use an
<input type="file">field to allow users to select files for uploading. -
Back-End: Use the
IFormFileinterface in ASP.NET Core to handle the uploaded files.
Example:
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file != null && file.Length > 0)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "uploads", file.FileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Ok("File uploaded successfully.");
}
return BadRequest("No file uploaded.");
}
13. How do you handle versioning of a database in a .NET application?
Answer:
For database versioning:
-
Entity Framework Migrations: Use EF Core migrations to manage schema changes. When the schema changes, create a migration using
dotnet ef migrations add <MigrationName>. -
Manual Versioning: Maintain a version table in your database, and track schema versions in code.
14. How do you handle background tasks or long-running processes in .NET?
Answer:
To handle background tasks:
-
Hangfire: Use Hangfire to run background tasks in a recurring or delayed manner without blocking the main thread.
-
Azure Functions: For cloud applications, use Azure Functions to run background tasks asynchronously in the cloud.
15. How would you secure a .NET Web API against common security vulnerabilities?
Answer:
To secure your API:
-
Input Validation: Always validate incoming data to prevent SQL Injection and Cross-Site Scripting (XSS).
-
Authentication & Authorization: Use OAuth 2.0, JWT or ASP.NET Core Identity for securing access to your API.
-
CORS: Use Cross-Origin Resource Sharing (CORS) to limit which domains can access your API.
-
Rate Limiting: Protect against Denial of Service (DoS) attacks by limiting the rate of API calls.