Tidy up - Unused Project and Nuget package reference using Visual Studio 2019

If you are a Developer/Architect using Visual Studio as IDE for your development activities, this blog post will be of your interest. During the Ignite 2021 conference, Microsoft released Visual Studio 2019 v16.9 and v16.10 Preview 1. As part of version 16.10 Preview 1, one of the cool features they introduced is to "Remove Unused References..." for any Projects and Nuget packages that are not in use. At the time of writing this blog post, we have Visual Studio Version 16.10.0 (official release) which includes this new feature.  As part of development, we generally get carried away and introduce new Nuget package references to your project and add new references to your Projects. By the end of development, you will not be 100% sure which are not being referenced and unused which means you will leave those unused project references in your application. Now you might be wondering what's the big deal in it since it doesn't harm. The advantage of removing unused project r

Error Handling in .NET Core

Exception handling is one of the most important features of any application. To handle exceptions, we can use Try-Catch block in our code base. If we want to extract all the exception handling in one location .NET core provides Exception handler/middleware.
This article will refer to the following sample code on GitHub:

Exceptions with Try-Catch-Finally

The simplest form of a try-catch block 
try
{
   // try something here

} catch (Exception ex)
{
  // catch an exception here
finally
{
   // always run this code
}

You can have multiple catch blocks to handle specific exceptions like ArgumentOutOfRangeException, NullReferenceException etc. Finally block is optional, whether or not an exception has occurred, the finally block will always be executed.

Generally different approach is followed for error handling for front end application (using MVC, Razor) vs WebAPI.

Error handling for MVC/Razor

MVC actions are typically executed as a result of a user action in the browser so returning an error page to the browser is ideal. With MVC, failure to display a friendly error page is not a good practice in a production ready application. The default template uses the DeveloperExceptionPage middleware in a development environment but redirects to a shared Error view in non-development scenarios. Logic is implemented in the Configure() method of the Startup.cs class.

if (env.IsDevelopment())
{
   app.UseDeveloperExceptionPage();
}
else
{
   app.UseExceptionHandler("/Home/Error");
}


MVC Pages

In MVC project’s Home Controller, the Error() action method sets the RequestId to the current Activity.Current.Id if available or else it uses HttpContext.TraceIdentifier. These values will be useful during debugging.

For non-dev scenarios, the shared Error view can be further customized by updating the Error.cshtml view in the Shared subfolder.

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
   return View(new ErrorViewModel { 
      RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier 
   });

Refer to Project WebAppMVCNetCore2.1 in the following GitHub link https://tinyurl.com/sqx65mn

Razor Pages

In Razor projects for the non-dev scenario is slightly different for Razor Pages. Instead of pointing to the Home controller’s Error() action method, it points to the to the /Error page route. This Error.cshtml Razor Page found in the root level of the Pages folder.

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public class ErrorModel : PageModel
    {
        public string RequestId { get; set; }

        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

        public void OnGet()
        {
            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
        }
    }

Refer to Project RazorApp.Net2.1 in the following GitHub link https://tinyurl.com/sqx65mn


WebAPI handling error using Built-In Middleware

UseExceptionHandler middleware is a built-in middleware that we can use to handle exceptions in our ASP.NET Core Web API application

if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(appError =>
                {
                    appError.Run(async context =>
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        context.Response.ContentType = "application/json";

                        var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                        if (contextFeature != null)
                        {

                            await context.Response.WriteAsync(new Error
                            {
                                StatusCode = context.Response.StatusCode,
                                Message = "Internal Server Error."
                            }.ToString());
                        }
                    });
                });
            } 


Refer to Project WebApiBuiltInMiddleware.Net2.1 in the following GitHub link https://tinyurl.com/sqx65mn

WebAPI handling error using Custom Middleware

The above example works for simple scenarios if you want more control or logic you can write your custom middleware and can flush logic associated to how we need to handle errors.
public class ExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<ExceptionMiddleware> _logger;

        public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
        {
            _logger = logger;
            _next = next;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                _logger.LogError($"Something went wrong: {ex}");
                await HandleExceptionAsync(httpContext, ex);
            }
        }

        private Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;

            return context.Response.WriteAsync(new Error
            {
                StatusCode = context.Response.StatusCode,
                Message = "Internal Server Error from the custom middleware."
            }.ToString());
        }
    }


Refer to Project WebApiCustomMiddleware.Net2.1 in the following GitHub link https://tinyurl.com/sqx65mn

WebAPI handling error using Exception Handling Path (.NET Core 2.1/2.2)

1. In Startup Configure, invoke UseExceptionHandler to use the middleware
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseExceptionHandler("/error-local-development");
            }
            else
            {
                app.UseExceptionHandler("/error");
            }

            app.UseMvc();
        }
2.  Configure a controller action to respond to the /error route
[AllowAnonymous]
[Route("/error")]
public IActionResult Error([FromServices] IHostingEnvironment webHostEnvironment)
        {
            var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
            var ex = feature?.Error;
            var isDev = webHostEnvironment.IsDevelopment();
            var problemDetails = new ProblemDetails
            {
                Status = (int)HttpStatusCode.InternalServerError,
                Instance = feature?.Path,
                Title = isDev ? $"{ex.GetType().Name}: {ex.Message}" : "An error occurred.",
                Detail = isDev ? ex.StackTrace : null,
            };

            return StatusCode(problemDetails.Status.Value, problemDetails);
        }

Refer to Project WebApiExceptionHandlingPath.Net2.1 in the following GitHub link https://tinyurl.com/sqx65mn

WebAPI handling error using Exception Handling Path (.NET Core 3.1)

1. In Startup Configure, invoke UseExceptionHandler to use the middleware
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseExceptionHandler("/error-local-development");
            }
            else
            {
                app.UseExceptionHandler("/error");
            }

            app.UseMvc();
        }
2.  Configure a controller action to respond to the /error route
[Route("/error")]
public IActionResult Error() => Problem();

Refer to Project WebApiExceptionHandlingPath.Net3.1 in the following GitHub link https://tinyurl.com/sqx65mn

Comments

Popular posts from this blog

Tidy up - Unused Project and Nuget package reference using Visual Studio 2019

Swagger UI for Azure Function v2 & v3 APIs

Authenticate Azure Functions - API Keys