
Welcome to triksbuddy blog. He we discuss on different technology, tips and tricks, programming, project management and leadership. Here we share technology tutorials, reviews, comparison, listing and many more. We also share interview questions along with answers on different topics and technologies. Stay tuned and connected with us and know new technologies and dig down known ones.
Tuesday, April 18, 2023
What is the difference between a Docker container and a virtual machine?
The main difference between the two is that containers are more lightweight and efficient than virtual machines since they share the host machine's kernel and can start up and shut down faster. Additionally, containers are more scalable since they can be easily replicated and moved between hosts. On the other hand, virtual machines offer better isolation since they have their own virtual hardware and can run different operating systems on the same physical host.

How do you use health checks in .NET Core?
In .NET Core, you can use health checks to monitor the health of your application's dependencies and components, such as databases, external services, and disk space. Health checks can help you quickly identify issues and troubleshoot problems before they cause downtime.
To use health checks in .NET Core, you can add the Microsoft.Extensions.Diagnostics.HealthChecks NuGet package to your project. Then, you can define your health checks by creating classes that implement the IHealthCheck interface. The IHealthCheck interface has a single CheckHealthAsync method that returns a Task<HealthCheckResult>.
Here's an example of a custom health check that checks the status of a database:
public class DatabaseHealthCheck : IHealthCheck
{
private readonly IDbConnection _dbConnection;
public DatabaseHealthCheck(IDbConnection dbConnection)
{
_dbConnection = dbConnection;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
try
{
await _dbConnection.OpenAsync(cancellationToken);
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Database connection failed", ex);
}
return HealthCheckResult.Healthy();
}
}
Once you have defined your health checks, you can register them with the IHealthChecksBuilder in the ConfigureServices method of your Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddCheck<DatabaseHealthCheck>("database");
}
This registers the DatabaseHealthCheck as a health check named "database". You can then use the UseHealthChecks method in your app.UseEndpoints configuration to map the health check endpoint to a specific URL:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
This maps the health check endpoint to /health. You can then make requests to /health to get a JSON response that indicates the status of your application's health checks.

What is the difference between a 404 and a 500 error in ASP.NET Core?
In ASP.NET Core, a 404 error occurs when the requested resource is not found on the server. This can happen, for example, if the URL is incorrect or if the requested page has been deleted.
On the other hand, a 500 error (Internal Server Error) occurs when the server encounters an error while processing the request. This can happen due to various reasons, such as a bug in the code, an issue with the server configuration, or a problem with the database connection.
In general,
a 404 error is a client-side error, meaning that the problem lies with the client's request, while
a 500 error is a server-side error, meaning that the problem lies with the server.

What is Exception Handling? How do you implement exception handling in .NET Core?
Exception Handling:
Exception handling is the process of responding to runtime errors or exceptional conditions in a controlled manner
to prevent program crashes or undefined behavior. In .NET, exceptions are represented by the
System.Exception
class and its derivatives.
Exception handling helps maintain the stability, reliability, and usability of applications.
In .NET Core, error handling can be implemented using several techniques, depending on the application type (e.g., web, desktop, or console). Common approaches include:
Exception handling in .NET is a robust process aimed at managing errors gracefully while ensuring application reliability and user satisfaction. Below is a detailed explanation of all major methods, processes, and techniques, complete with examples, implementation details, and use cases.
1. Structured Exception Handling (SEH)
This is the foundation of exception handling in .NET and involves the use of try
, catch
, finally
, and throw
.
How It Works
try
block: Encloses the code that might throw exceptions.catch
block: Catches specific exceptions and handles them.finally
block: Executes cleanup code regardless of whether an exception occurred.throw
: Used to propagate exceptions.
Example
try
{
int number = int.Parse("invalid"); // Will throw FormatException
}
catch (FormatException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
Console.WriteLine("Execution completed.");
}
Use Cases
- Handling runtime errors like parsing, file I/O, or network connectivity issues.
- Ensuring resources are released (e.g., closing a file handle).
2. Global Exception Handling in ASP.NET Core
In web applications, centralizing error handling improves maintainability and ensures consistent error responses.
How to Implement
Custom Middleware:
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
public GlobalExceptionMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
var response = new { message = "An unexpected error occurred." };
return context.Response.WriteAsJsonAsync(response);
}
}
Register Middleware in Program.cs
:
app.UseMiddleware<GlobalExceptionMiddleware>();
Use Cases
- Providing unified error responses for REST APIs.
- Logging and masking sensitive errors.
3. Developer Exception Page
A built-in feature in ASP.NET Core for detailed error information during development.
How It Works
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Use Cases
- Debugging during development.
- Quickly identifying the root cause of exceptions.
4. Exception Filters
Filters are action-level or global handlers in ASP.NET Core MVC for catching exceptions.
How to Implement
Custom Exception Filter:
public class CustomExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
context.Result = new JsonResult(new { error = context.Exception.Message })
{
StatusCode = 500
};
}
}
Register Filter Globally:
services.AddControllers(options =>
{
options.Filters.Add<CustomExceptionFilter>();
});
Use Cases
- Handling specific exceptions at the controller level.
- Logging or transforming exceptions into meaningful HTTP responses.
5. Logging Exceptions
Logging ensures you capture errors for debugging, monitoring, and auditing.
How to Implement
try
{
throw new InvalidOperationException("Example exception");
}
catch (Exception ex)
{
ILogger logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<Program>();
logger.LogError(ex, "An error occurred");
}
Use Cases
- Monitoring application health.
- Analyzing trends and patterns in production errors.
6. Using Exception Filters in Middleware
Exception filters can be added as middleware for fine-grained error handling.
How It Works
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
try
{
await next.Invoke();
}
catch (Exception ex)
{
// Handle the exception
context.Response.ContentType = "application/json";
context.Response.StatusCode = 500;
await context.Response.WriteAsync(new { error = ex.Message }.ToString());
}
});
}
Use Cases
- Centralizing exception handling in middleware pipelines.
- Ensuring custom responses for all unhandled exceptions.
7. Graceful Shutdown Handling
Ensure resources are released and errors are managed during application shutdown.
How It Works
public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var lifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();
lifetime.ApplicationStopping.Register(OnApplicationStopping);
await host.RunAsync();
}
private static void OnApplicationStopping()
{
Console.WriteLine("Application is shutting down gracefully.");
}
}
Use Cases
- Releasing resources like database connections.
- Handling cleanup tasks during server shutdown.
8. Validation and Guard Clauses
Proactively prevent exceptions by validating input and business logic upfront.
How It Works
public void ProcessOrder(Order order)
{
if (order == null)
throw new ArgumentNullException(nameof(order));
if (order.Quantity <= 0)
throw new ArgumentException("Quantity must be greater than zero.");
}
Use Cases
- Validating user inputs in web forms or APIs.
- Ensuring preconditions for business logic.
9. Async Exception Handling
Manage exceptions in asynchronous programming effectively to avoid unobserved task errors.
How It Works
public async Task ProcessDataAsync()
{
try
{
await Task.Run(() => throw new InvalidOperationException("Async error."));
}
catch (Exception ex)
{
Console.WriteLine($"Caught exception: {ex.Message}");
}
}
Use Cases
- Handling exceptions in asynchronous workflows.
- Avoiding app crashes due to unobserved task exceptions.
10. Retry Mechanisms and Polly Library
Use retry mechanisms to handle transient exceptions like network issues.
How It Works
var retryPolicy = Policy
.Handle<HttpRequestException>()
.Retry(3, (exception, retryCount) =>
{
Console.WriteLine($"Retrying... Attempt: {retryCount}");
});
retryPolicy.Execute(() =>
{
// Code that might throw exceptions
HttpClient client = new HttpClient();
client.GetAsync("https://example.com").Wait();
});
Use Cases
- Retrying failed HTTP requests in APIs.
- Handling transient database connection errors.
11. Circuit Breaker Pattern
Prevent application overload by implementing the circuit breaker pattern using Polly or custom logic.
How It Works
var circuitBreakerPolicy = Policy
.Handle<Exception>()
.CircuitBreaker(2, TimeSpan.FromSeconds(30),
onBreak: (ex, duration) => Console.WriteLine($"Circuit broken for {duration}"),
onReset: () => Console.WriteLine("Circuit reset"));
circuitBreakerPolicy.Execute(() =>
{
// Code that might throw exceptions
throw new InvalidOperationException("Simulated failure.");
});
Use Cases
- Preventing cascading failures in distributed systems.
- Limiting retries during persistent failures.
Summary of Exception Handling Techniques and Use Cases
Technique | Use Cases |
---|---|
Try-Catch Blocks |
|
Global Exception Handling |
|
Custom Exceptions |
|
Exception Filters |
|
Graceful Shutdown Handling |
|
Validation and Guard Clauses |
|
Async Exception Handling |
|
Retry Mechanisms |
|
Circuit Breaker Pattern |
|
By combining these techniques, you can build resilient, user-friendly, and maintainable applications in .NET.

What is the difference between a value type and a reference type in .NET Core?
A value type represents a single value, such as an integer or a floating-point number, and is stored directly in memory. When you create a variable of a value type, the memory is allocated on the stack, and the value is stored in that memory location. Examples of value types in .NET Core include integers, floating-point numbers, Boolean values, and enums.
A reference type, on the other hand, represents a reference to an object that is stored in memory. When you create a variable of a reference type, the memory is allocated on the heap, and the variable holds a reference to the memory location where the object is stored. Examples of reference types in .NET Core include classes, interfaces, and delegates.
One important difference between value types and reference types is how they are treated when passed to a method or assigned to a variable. When a value type is passed to a method or assigned to a variable, a copy of its value is created. This means that changes made to the copy do not affect the original value. With reference types, however, only a reference to the object is passed or assigned, not the object itself. This means that changes made to the object through the reference affect the original object.
Another difference is that value types have a default value, which is the value that is assigned to a variable of that type if no other value is specified. For example, the default value for an integer is 0. Reference types, on the other hand, have a default value of null, which means that they do not refer to any object.

What is a memory stream in .NET Core and how do you use it?
In .NET Core, a MemoryStream is a stream that uses memory as its backing store rather than a file or network connection. It allows you to read and write data as if it were being read from or written to a file, but in reality, the data is being stored in memory.
You can create a new MemoryStream instance using the following code:
var stream = new MemoryStream();
Once you have created a MemoryStream instance, you can use it to read from or write to the stream. For example, to write some data to the stream, you can use the Write method:
byte[] buffer = Encoding.UTF8.GetBytes("Hello, world!");
stream.Write(buffer, 0, buffer.Length);
To read data from the stream, you can use the Read method:
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
You can also use the Position property to get or set the current position within the stream, and the Length property to get the length of the data in the stream.
MemoryStream is often used in scenarios where you need to work with data that is too small or too volatile to justify the overhead of using a file or network connection. It can also be used for testing and debugging purposes, or as an alternative to writing data to a file.

What is a CancellationToken in .NET Core and how do you use it?
In .NET Core, a CancellationToken is a mechanism for cancelling long-running operations. It is typically used in conjunction with asynchronous operations to allow the user to cancel a task that is taking too long to complete. A CancellationToken represents a request to cancel an operation, and can be passed to a method as a parameter.
To use a CancellationToken, you first create an instance of the CancellationTokenSource class, which provides a Token property that returns a CancellationToken. This token can then be passed to a method that supports cancellation, such as a Task.Run method that runs an asynchronous operation. Within the operation, you periodically check the IsCancellationRequested property of the CancellationToken to see if the user has requested cancellation. If cancellation has been requested, you can perform any necessary cleanup and return early from the operation.
Here is an example of how to use a CancellationToken:
public async Task DoWorkAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
// Perform work here
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
In this example, the DoWorkAsync method performs some long-running work in a loop. The cancellationToken parameter is passed in by the caller and is used to check if cancellation has been requested. The Task.Delay method is used to simulate the work being performed, but in a real application, this would be replaced with actual work.

What is a Task in .NET Core and how does it differ from a Thread?
In .NET Core, a Task represents an asynchronous operation that can be scheduled on a thread pool thread. When an asynchronous operation is started, it returns a Task object that can be used to monitor the progress of the operation or to wait for its completion. Task objects provide a number of methods for working with asynchronous operations, such as ContinueWith and WhenAll.
On the other hand, a Thread represents an independent path of execution within a process. When a thread is started, it begins executing code on a separate call stack. Unlike Task, Thread objects are not specifically designed for asynchronous operations, although they can be used for that purpose. However, using Thread directly for asynchronous operations is generally discouraged in favor of Task or other asynchronous programming patterns, because it can result in inefficient use of system resources.

How do you use async/await in .NET Core?
Async/await is a programming pattern in .NET Core that allows you to write asynchronous code in a more readable and manageable way. Here's an example of how to use async/await in .NET Core:
public async Task<int> CalculateSumAsync(int a, int b)
{
int sum = await LongRunningCalculationAsync(a, b);
return sum;
}
public async Task<int> LongRunningCalculationAsync(int a, int b)
{
await Task.Delay(1000); // Simulate long running operation
return a + b;
}
In this example, the CalculateSumAsync method is marked with the async keyword, which indicates that it contains asynchronous code. The method returns a Task<int> instead of an int to indicate that it is an asynchronous operation that will complete at some point in the future.
The LongRunningCalculationAsync method is also marked with the async keyword, and contains a call to the Task.Delay method to simulate a long running operation. The await keyword is used to indicate that the method should wait for the Task.Delay operation to complete before returning the result.
To use the CalculateSumAsync method, you can simply call it like this:
int sum = await CalculateSumAsync(2, 3);
The await keyword is used again to indicate that the calling method should wait for the CalculateSumAsync operation to complete before continuing.
Overall, async/await is a powerful and flexible pattern in .NET Core that allows you to write efficient and responsive code that can handle long-running operations without blocking the calling thread.

What is the difference between IQueryable and IEnumerable in .NET Core?
In .NET Core, IQueryable and IEnumerable are both interfaces that represent a collection of objects. However, there are some key differences between the two:
1. Deferred execution: IQueryable supports deferred execution, meaning that it does not execute the query until the results are enumerated. This allows for more efficient queries, as it only retrieves the data that is necessary. IEnumerable, on the other hand, does not support deferred execution.
2. Expression tree: IQueryable uses expression trees to represent the query, while IEnumerable uses delegates. Expression trees are more powerful and allow for more complex queries to be constructed and analyzed at runtime.
3. Query provider: IQueryable has a query provider, which is responsible for translating the expression tree into a SQL query or some other data source query. This allows for more flexibility in the types of data sources that can be queried. IEnumerable does not have a query provider and is limited to in-memory collections.
