Search code examples
c#asp.net-corecookies.net-coreasp.net-core-mvc

How to use IHttpContextAccessor in static class to set cookies


I am trying to create a generic addReplaceCookie method in a static class. The method would look something like this

public static void addReplaceCookie(string cookieName, string cookieValue)
{

    if ((HttpContext.Current.Request.Cookies(cookieName) == null))
    {
        // add cookie
        HttpCookie s = new HttpCookie(cookieName);
        s.Value = cookieValue;
        s.Expires = DateTime.Now.AddDays(7);
        HttpContext.Current.Response.Cookies.Add(s);
    }
    else {
        // ensure cookie value is correct 
        HttpCookie existingSchoolCookie = HttpContext.Current.Request.Cookies(cookieName);
        existingSchoolCookie.Expires = DateTime.Now.AddDays(7);
        existingSchoolCookie.Value = cookieValue;
        HttpContext.Current.Response.Cookies.Set(existingSchoolCookie);
    }

}

I know that in order to get the HttpContext in asp.net core you have to use the IHttpContextAccessor. But I cannot inject it into a static class.

Is there another way to get access to it?

I am using rc1-final.


Solution

  • While i would advise staying away from static class scenarios like this, it is still possible to achieve what you are asking for.

    Assuming a static class like...

    public class MyStaticHelperClass {
        private static IHttpContextAccessor httpContextAccessor;
        public static void SetHttpContextAccessor(IHttpContextAccessor  accessor) {
            httpContextAccessor = accessor;
        }
    
        public static void addReplaceCookie(string cookieName, string cookieValue) {
            var HttpContext = httpContextAccessor.HttpContext;
            if (HttpContext.Request.Cookies(cookieName) == null) {
                // add cookie
                HttpCookie s = new HttpCookie(cookieName);
                s.Value = cookieValue;
                s.Expires = DateTime.Now.AddDays(7);
                HttpContext.Response.Cookies.Add(s);
            } else {
                // ensure cookie value is correct 
                HttpCookie existingSchoolCookie = HttpContext.Request.Cookies(cookieName);
                existingSchoolCookie.Expires = DateTime.Now.AddDays(7);
                existingSchoolCookie.Value = cookieValue;
                HttpContext.Response.Cookies.Set(existingSchoolCookie);
            }
        }
    }
    

    You would add the accessor in Startup.ConfigureServices since it is no longer added automatically

    public void ConfigureServices(IServiceCollection service) {
    
        //Register IHttpContextAccessor and its implementation.
        services.AddHttpContextAccessor();
    
        services.AddTransient<IMyService, MyService>();
        services.AddMvc();
    
        //...
    }
    

    And get the service via injection into the Startup.Configure method

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor accessor)
    {
        MyStaticHelperClass.SetHttpContextAccessor(accessor);
    
        //...
    
    }
    

    Now with that done. I would still strongly advise converting your static class into a service whose concrete implementation would use the IHttpContextAccessor as a dependency that can be injected via its constructor.

    public interface ICookieService {
        void AddReplaceCookie(string cookieName, string cookieValue);
    }
    
    public class CookieService : ICookieService {
        IHttpContextAccessor httpContextAccessor;
        public CookieService(IHttpContextAccessor httpContextAccessor) {
            this.httpContextAccessor = httpContextAccessor;
        }
        public void AddReplaceCookie(string cookieName, string cookieValue) {
            var HttpContext = httpContextAccessor.HttpContext;
            if (HttpContext.Request.Cookies(cookieName) == null) {
                // add cookie
                HttpCookie s = new HttpCookie(cookieName);
                s.Value = cookieValue;
                s.Expires = DateTime.Now.AddDays(7);
                HttpContext.Response.Cookies.Add(s);
            } else {
                // ensure cookie value is correct 
                HttpCookie existingSchoolCookie = HttpContext.Request.Cookies(cookieName);
                existingSchoolCookie.Expires = DateTime.Now.AddDays(7);
                existingSchoolCookie.Value = cookieValue;
                HttpContext.Response.Cookies.Set(existingSchoolCookie);
            }
        }
    }
    

    ...that could then be registered with the Services collection...

    public void ConfigureServices(IServiceCollection service) {
    
        services.AddHttpContextAccessor();
    
        services.AddTransient<ICookieService, CookieService>();
        services.AddMvc();
    }
    

    ...and be available for injection into classes that have need of it's use.

    public class SomeClassThatNeedCookieServicesController : Controller {
        ICookieService cookieService;
    
        public SomeClassThatNeedCookieServicesController(ICookieService cookieService) {
            this.cookieService = cookieService;
        }
    
        //...
    }
    

    This is how I do it to manage session cookies in my applications.