How to use IHttpContextAccessor in static class to set cookies

15,801

Solution 1

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.

Solution 2

If possible, don't use static class. But if you have to use, sending IHttpContextAccessor as a parameter might be a solution.

public static void addReplaceCookie(string cookieName, string cookieValue, IHttpContextAccessor accessor)
{
   //your code
}
public class CallerClass
{
   private readonly IHttpContextAccessor _accessor;

   public CallerClass(IHttpContextAccessor accessor)
   {
       _accessor = accessor;
       addReplaceCookie(cookieName, cookieValue, accessor);
   }
}

Solution 3

in Startup.ConfigureServices:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

later in Startup.Configure add by DI IServiceProvider and use it to extract IHttpContextAccessor like this:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider svp)
    {
        IHttpContextAccessor accessor = svp.GetService<IHttpContextAccessor>();
        MyRepository.SetHttpContextAccessor(accessor);
Share:
15,801
user973671
Author by

user973671

Updated on June 13, 2022

Comments

  • user973671
    user973671 almost 2 years

    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.

  • user973671
    user973671 almost 8 years
    Awesome, I think Im starting to get it. Do you know, is there a way to replace a cookie in asp.net core, or does append automatically replace it?
  • Nkosi
    Nkosi almost 8 years
    What do you mean by append? I'm not sure I understand. I normally use the Response.Cookies.Set(cookie) if that is what you mean. where the cookie has the key and value(s).
  • user973671
    user973671 almost 8 years
    Yea, for some reason Response.Cookies.Set is throwing an error for me. I have to use Response.Cookies.Append(cookieName, cookieValue, CookieOption); But thats fine. Thanks for your help!
  • amir
    amir about 4 years
    would you please describe why you don`t recommend static class for this scenarios and what is the scenarios you recommend for it?