Search code examples
c#asp.net-core-2.0asp.net-core-middleware

Is it possible to access data generated in Middleware?


I've set up a very simple middleware as a test project to learn, currently it just dumps out the request headers.

I was wondering, given the set-up below if it is possible to either:

  1. Populate a field within the Startup class (that can then be accessed via DI)
  2. or to directly access a field within the Middleware (say in OnActionExecuting)

Startup:

using HeaderAuthentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace ServiceLayer
{
    // ReSharper disable once ClassNeverInstantiated.Global
    public class Startup
    {
        private IConfiguration Configuration { get; }

        public Startup(IConfiguration Configuration)
        {
            this.Configuration = Configuration;
        }

        // ReSharper disable once UnusedMember.Global
        public void ConfigureServices(IServiceCollection Services)
        {
            Services.AddMvc().AddJsonOptions(Options =>
               Options.SerializerSettings.ReferenceLoopHandling =
                   Newtonsoft.Json.ReferenceLoopHandling.Ignore
            );
        }

        // ReSharper disable once UnusedMember.Global
        public void Configure(
            IApplicationBuilder App,
            IHostingEnvironment Env,
            ILoggerFactory LoggerFactory
        )
        {
            App.UseHeaderChecking();

            if (Env.IsDevelopment())
            {
                App.UseDeveloperExceptionPage();
            }

            App.UseMvc();
        }
    }
}

Extension method:

using Microsoft.AspNetCore.Builder;

namespace HeaderAuthentication
{
    public static class RequestHeaderCheckingMiddleware
    {
        public static IApplicationBuilder UseHeaderChecking(
            this IApplicationBuilder Builder
        )
        {
            return Builder.UseMiddleware<CheckHeaders>();
        }
    }
}

CheckHeader code:

using InterfaceLayer.Entities;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace HeaderAuthentication
{
    public class CheckHeaders
    {
        private readonly RequestDelegate Next;

        public CheckHeaders(RequestDelegate NextDelegate)
        {
            Next = NextDelegate;
        }

        public Task Invoke(HttpContext Context, SupportContext Support)
        {
            if (Context.Request == null)
            {
                //return null;
            }

            var testA = GetRequestHeader(Context, "X-HeaderTest-A"); // sandwich
            var testB = GetRequestHeader(Context, "X-HeaderTest-B"); // biscuit

            return Next(Context);
        }

        private static string GetRequestHeader(HttpContext Context, string Key)
        {
            if (!Context.Request.Headers.TryGetValue(Key, out var buffer))
            {
                return string.Empty;
            }

            return buffer;
        }
    }
}

I'd like to access the values within testA and testB within the OnActionExecuting method within my BaseController to trigger the "sandwich" and "biscuit" cases, as below:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;

namespace ServiceLayer.Controllers
{
    public partial class BaseController : Controller
    {
        public BaseController()
        {
        }

        public override void OnActionExecuting(ActionExecutingContext Context)
        {
            switch (testValue)
            {
                case "sandwich":
                    break;
                case "biscuit":
                    break;
            }

            base.OnActionExecuting(Context);
        }
    }
}

Is this feasible?


Solution

  • A dirty way could be your values into the Context.Items collection under a separate well known key inside CheckHeaders.Invoke method, and to query the context items for the presence of the values inside BaseController.OnActionExecuting method and dependig on it to act appropriately.