Skip to content

A better approach to use HttpContext outside a Controller in .Net Core 2.1

Last updated on April 1, 2019

Introduction

In my previous post we discussed an approach to access the HttpContext.Session in RequestHandler. However, there was a problem. For every single component where we need to access the session, we have to inject a dependency of IHttpContextAccessor. While for one or two components it’s not a problem, it can be very daunting if we have to do the same over and over again. In this article, we will use a different approach to achieve the same.

The AppContext

In this approach, we are going to create a static AppContext class. This class going to hold the current Http session as a property called Current. In our previous approach, we used the IHttpContextAccessor to get the current Http session, likewise we are gonna do here. However, since I want to keep the AppContext static, we need a static method to inject IHttpContextAccessor to it, as shown in the code below:

using Microsoft.AspNetCore.Http;

namespace StaticHttpContextAccessor.Helpers
{
    public static class AppContext
    {
        private static IHttpContextAccessor _httpContextAccessor;

        public static void Configure(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public static HttpContext Current => _httpContextAccessor.HttpContext;
    }
}

 

The Startup Class

The Startup class in this case will be a little different from the previous one. We still need to add the IHttpContextAccessor to the ConfigureServices method. It is the ConfigureService method where we will inject the IHttpContextAccessor into the AppContext. And, to achieve that we are going to use the IApplicationBuilder as shown below:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StaticHttpContextAccessor.Helpers;

namespace StaticHttpContextAccessor
{
    public class Startup
    {
        public Startup(IConfiguration configuration) { Configuration = configuration; }
        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options => {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddSession();
            services.AddHttpContextAccessor();
            services.AddSingleton<RequestHandler>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
            else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); }
            app.UseHttpsRedirection();
            app.UseCookiePolicy();

            app.UseSession();
            AppContext.Configure(app.ApplicationServices
                      .GetRequiredService<IHttpContextAccessor>());

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

 

ISession Extensions

Just for fun, I added a few extension methods for ISession though it’s not really required. But if you find them useful, go ahead to consume them in a real life project:

using Microsoft.AspNetCore.Http;  
using Newtonsoft.Json;  
  
namespace StaticHttpContextAccessor.Helpers  
{  
    public static class HttpSessionHelper  
    {  
        public static void Set<T>(this ISession session, string key, T value)  
        {  
            session.SetString(key, JsonConvert.SerializeObject(value));  
        }  
  
        public static T Get<T>(this ISession session, string key)  
        {  
            var value = session.GetString(key);  
            return value == null ? default(T) :  
                JsonConvert.DeserializeObject<T>(value);  
        }  
    }  
}

 

The RequestHandler and HomeController

Now that we have the setup ready, it’s time to set the message in our RequestHandler using the AppContext which gives us the current session. We can then get the mesage from the session in the controller, as we did in our previous approach. Please refer to the code below:

namespace StaticHttpContextAccessor.Helpers  
{  
    public class RequestHandler  
    {  
        public void HandleIndexRequest()  
        {  
            // do something for the request  
  
            var message = "This is a much cleaner approach to access Session!";  
            AppContext.Current.Session.Set<string>("message", message);  
        }  
    }  
}
using Microsoft.AspNetCore.Mvc;  
using StaticHttpContextAccessor.Helpers;  
  
namespace StaticHttpContextAccessor.Controllers  
{  
    public class HomeController : Controller  
    {  
        private readonly RequestHandler _requestHandler;  
  
        public HomeController(RequestHandler requestHandler)  
        {  
            _requestHandler = requestHandler;  
        }  
  
        public IActionResult Index()  
        {  
            _requestHandler.HandleIndexRequest();  
            ViewData["Message"] = HttpContext.Session.Get<string>("message");  
            return View();  
        }  
    }  
}

 

Summary

If I compare this approach with the previous one, this one feels much cleaner. I would be more than happy to know what you guys think about the two. Which one would you choose and why? Please do let me know in the comments below.

If you have not read my previous article discussing the first approach, you can find the same here.

 

Published in.Net Core