Saturday, July 11, 2015

ASP.NET Core / MVC 6 HttpContext.Current

As you know with MVC 6, HttpContext is rewritten and one of the most used functionality , HttpContext.Current is dropped. In most situations you don’t need this and you should use Controller context. But in some situations you may need access to HttpContext. In my scenario I want to pass some data using HttpContext.Items from one layer (middleware) to another (business layer).

Below are the two ways to get current HttpContext:

  • Using dependency injection we can inject the HttpContext on to the service directly. DI injects a singleton object called HttpContextAccessor which is used to retrieve the current HttpContext. Here is the sample code for this

    public class MyService
    {
        private HttpContext context;
        public MySerivce(IHttpContextAccessor contextAccessor)
        {
            this.context = contextAccessor.HttpContext;
        }

  •  Similar to HttpContext.Current we can also create a static class that holds the reference for the current HttpContext. Here is the code for this static class

    public static class HttpHelper
    {
        private static IHttpContextAccessor HttpContextAccessor;
        public static void Configure(IHttpContextAccessor httpContextAccessor)
        {
            HttpContextAccessor = httpContextAccessor;
        }

        public static HttpContext HttpContext
        {
            get
            {
                return HttpContextAccessor.HttpContext;
            }
        }
    }

This static HttpHelper class stores the singleton HttpContextAccessor and is then used to return the current HttpContext. We will configure our HttpHelper in our startup as shown below

        public void Configure(IApplicationBuilder app)
        {
            //other code
            HttpHelper.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());
        }

Finally we can get current HttpContext wherever we need using our Helper as below
HttpHelper.HttpContext

As you see using the above two approaches to get the current HttpContext.

Please see my updated post on this. I am using CallContext to pass the HttpContext and other data
ASP.NET Core Async Context Data

30 comments:

  1. I have been looking day and night for this solution, thank you!

    ReplyDelete
  2. I have using the belo code for exporting file in server side . how can i need to change for MVC6
    HttpContext.Current.Response.AddHeader("content-type", "text/Calendar");
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
    HttpContext.Current.Response.BinaryWrite(Buffer);
    HttpContext.Current.Response.End();

    ReplyDelete
    Replies
    1. i am unable to access IHttpContextAccessor in my page

      Delete
  3. Srini, In MVC we should use FileResult to download a file. Please take a look at this URL on how to download a calendar file to the user
    http://rayaspnet.blogspot.in/2013/01/how-to-generate-and-download-icalendar.html

    ReplyDelete
  4. Hi Prasanna, we have used separate class as InternetCalendaring for processing and adding the description, subject and other things. we have used this scenario for both asp and mvc too. so i prefer this way of using httpcontext.
    string fileName = "iCalender.ics";
    InternetCalendaring.ICSBuilder icsbBuilder = new InternetCalendaring.ICSBuilder(vecVEvents);
    sRes = icsbBuilder.ICSBuildProcess();
    byte[] Buffer = Encoding.Unicode.GetBytes(sRes);
    HttpContext.Current.Response.AddHeader("content-type", "text/Calendar");
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
    HttpContext.Current.Response.BinaryWrite(Buffer);
    HttpContext.Current.Response.End();

    ReplyDelete
    Replies
    1. What is the issue you are facing while accessing the HttpContext in your class.

      Here is the code that is working for me:
      HttpHelper, a singleton class that keeps reference of the current context
      https://github.com/Nootus/MegaMine/blob/master/MegaMine/src/eMine/Lib/Shared/HttpHelper.cs

      Startup.cs file where we setup the HttpHelper (last line in this class)
      https://github.com/Nootus/MegaMine/blob/master/MegaMine/src/eMine/Startup.cs

      Here I am assessing the HttpContext using HttpHelper
      https://github.com/Nootus/MegaMine/blob/master/MegaMine/src/eMine/Lib/Shared/Profile.cs

      Delete
  5. Great Article!

    Do you know how to get the Controller and Action name from a HttpContextAccessor instance?

    Thanks a lot.

    ReplyDelete
    Replies
    1. With RC1 try this code
      var contextAccessor = HttpContextAccessor.HttpContext.RequestServices.GetService(typeof(Microsoft.AspNet.Mvc.Infrastructure.IActionContextAccessor)) as IActionContextAccessor;
      string controller = contextAccessor.ActionContext.RouteData.Values["controller"].ToString();

      With RC2 this will be easy
      HttpContextAccessor.HttpContext.GetRouteValue("controller")

      Please keep in mind that you may not be able to access the controller name in the Middleware as RouteData is populated at the end

      Delete
  6. Hi one question,

    i have create an application with mvc 6, other application will redirect to mine, before we were obtaining all the user info from httpApplication now how can i read the values if theres no httpApplication on mvc6?

    ReplyDelete
  7. In ASP.NET Core you can get the current logged in User inside the controller using this.HttpContext.User. If you want to get the user info outside the controller, you can use the approach I mentioned above.

    ReplyDelete
  8. Hi thanks for the quick reply, the issue is before we were doing this

    return (HttpContext.ApplicationInstance as IGlobalContext);

    IGlobalContext its an interface like this

    public interface IGlobalContext
    {
    string Culture { get; }
    DistributorProfileModel CurrentDistributor { get; }
    }

    So the applicationInstance on httpContext contained all the info from current distributor, now i dont know how to obtain that information since httpApplication no longer exists, i believe the info must be there on the context but i dont know how to access now (maybe in the headers?)

    Thanks for your time

    ReplyDelete
    Replies
    1. Ivan, it seems you are using Application object to store your data (CurrentDistributor). This mechanism is discontinued in Core. You should use Caching. Please see the documentation on this
      https://docs.asp.net/en/latest/performance/caching/memory.html

      Delete
  9. thanks for the reply, i will take a look on cache, yeah the issue is that the main application where they login dont use core yet, once they login the user can enter to our application and thats how we got the user info, but now that my application its using core dont know how to retreive it, thanks for your help

    ReplyDelete

  10. Hi All,
    Thanks for this issue but
    It does not work for me...Asp.Net Core framewoek 4.6...HttpContext is null

    ReplyDelete
    Replies
    1. I am using this code in my project, let me know what is not working?

      Delete
  11. Thanks for this.... Really helped me.
    Nikhil

    ReplyDelete
  12. Thank you very much!

    ReplyDelete
  13. I'm sorry but when i tried to implement this solution, Visual Studio thrown this exception: No service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' has been registered.

    ReplyDelete
  14. I do not understand very well how your code works, I check it on the tester shows an error

    ReplyDelete