Source code
.NET .NET Core C# Visual Studio

Using Extension Methods in a .NET Core Application

Welcome to today’s post.

In today’s post I will be discussing extension methods and how they can be used in a .NET Core application.

Before I go into the details of how they are used within ASP.NET Core applications, I will give a brief overview of what an extension method is, why they are used, and the rules behind their use. I will also provide a basic example of how they are used with an example in C#.

What is an Extension Method?

Extension methods have already been part of the C# language library since they were introduced in version 3.0. Custom extension methods allow you to create additional methods to types without having to create methods within new derived types.

Custom extension methods allow you to create additional methods to types without having to create methods within new derived types.

For example, we want to create a method to compute the number of alphanumeric characters within a string, AlphanumericCount(). We can create this as a method within a new class, which we would have to build and use separately from our String type.

Extension types that allow query methods for enumerable types are provided by the System.Linq library.

Creating Extension Methods

Each extension method follows the rules:

  1. The method must be under a namespace.
  2. The method must be under a public static class.
  3. The method must be public visibility of static type.
  4. The method must contain a parameter with the type being extended and preceded by this modifier.

For example, our new string extension method would be implemented as shown:

using System.Linq;
using System.Text;
using System;

namespace StringExtensionMethods
{
    public static class StringExtensions
    {
        public static int AlphanumericCount(this String strval)
        {
            return strval.Count(char.IsLetterOrDigit);
        }
    }
}

To use the above extension method, declare the namespace, StringExtensionMethods then declare a variable of the type that is extended and use the extension method:

using StringExtensionMethods;
string myString = “I am over 21 years of age.”;
int intVal = myString.AlphanumericCount();

Note: Extension methods cannot access private or protected members of the extended class. Also, extension methods cannot override methods within the extending class.

Using Extension Methods within the .NET Core Web Application Builder Pipeline

In the application pipeline IAppBuilder within ASP.NET Core, we can make use of useful middleware extensions, including those for authentication, authorization, http requests. For example, to enable authentication we call the following extension method:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	...
    app.UseAuthentication();
	...
}

Authentication is then handled by the authentication service middleware service, IAuthenticationService. This allows our ASP.NET Core web application to authenticate users with Cookie based or JWT Bearer based tokens. In one of my previous posts, I show how to implement JWT token authentication in ASP.NET Core applications.

Extending Error Handlers within a .NET Core Web API

In a .NET Core API service application, the use of extension methods is quite abundant within the application builder pipeline. In particular, the use of the UseExceptionHandler() extension method middleware for handling errors is one of the more useful middleware extensions we can utilise to delegate our application errors, filter the error, then output the error response is a more user-friendly way to the caller.

To be able to implement an error handler extension method, we use the above extension method guidelines. A general exception handler is used in the production environment where we wish to sanitise the error instead of displaying the full error and stack trace, which might contain sensitive details.

Below is an example general extension handler (as a lambda function) we use within the Configure() method of the startup.cs file:

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

            var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
            if (contextFeature != null)
            {
                await context.Response.WriteAsync(
  	                new ErrorDetail()
                    {
                        StatusCode = context.Response.StatusCode,
                        Message = "Internal Server Error."
                    }.JsonConvert.SerializeObject(this)	
            }
        });
    });
    app.UseHsts();
}

The above error handler looks quite cumbersome, so we can move the error handler into a it’s own custom extension method, which is the error handler. 

We implement a custom.NET Core middleware extension class as follows:

using GeneralErrorHandling.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Net;

namespace GeneralErrorHandler.Extensions
{
    public static class ExceptionMiddlewareExtensions
    {
        public static void ConfigureExceptionHandler(this IApplicationBuilder app)
        {
            app.UseExceptionHandler(appError =>
            {
                appError.Run(async context =>
                {
                    context.Response.StatusCode = 500;
                    context.Response.ContentType = "application/json";

                    var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                    if (contextFeature != null)
                    { 
	                    var errorDetails = new ErrorDetails()
                        {
                            StatusCode = context.Response.StatusCode,
                            Message = "Internal Server Error."
                        };
                        await context.Response.WriteAsync(
                            JsonConvert.SerializeObject(errorDetails)
                        );
                    }
                });
            });
        }
    }
}

We also include a model to encapsulate the status code and error message:

namespace GeneralErrorHandler.Models
{
    public class ErrorDetail
    {
        public int StatusCode { get; set; }
        public string Message { get; set; }

    }
}

To use the middleware extension method from the startup.cs we do this as shown:

using GeneralErrorHandler.Extensions;

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.ConfigureExceptionHandler();
    ...
}

I have omitted logging in the above example. In a future post I will be discussing using the general exception handling with logging.

The above details have provided you with an overview of what extension methods are and how they are used in a few common scenarios, such as enabling security middleware and extending the exception handling middleware within an ASP.NET Core web application or ASP.NET Core web API application.

That’s all for today’s post.

I hope you found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial