44

I am working on couple of projects one of which is an ASP.NET 4.5 application and other one is .Net Core API 1.1 project. The asp.net application is using HttpContext classes to read cookies and page headers. Now, I need to move this to a .net standard library which can be used by both the project. I don't find HttpContext in .net standard SDK. Any suggestions?

Ahmad Adel
  • 136
  • 2
  • 11
Kumar A
  • 441
  • 1
  • 4
  • 3
  • 1
    Possible duplicate of [Access the current HttpContext in ASP.NET Core](https://stackoverflow.com/questions/31243068/access-the-current-httpcontext-in-asp-net-core) –  Nov 17 '17 at 19:14
  • You should not mix .NET and .NET Core projects, they do not run under the same framework. – Camilo Terevinto Nov 17 '17 at 19:19
  • Does the shared code really need to access these statics? Can you extract that logic? – Aluan Haddad Nov 17 '17 at 19:29

7 Answers7

32

There's a problem to your approach: .NET Standard is the most bare-bones implementation of .NET available, meaning that only basic features which are platform- and scenario-agnostic are implemented.
HttpContext exists on both the .NET Framework and .NET Core (both of which implement .NET Standard, by the way), but being specific to the Web, it does not exist on .NET Standard.

So, you have three options:

  1. Target the .NET Framework and use System.Web.HttpContext
  2. Target .NET Core and use Microsoft.AspNetCore.Http.HttpContext
  3. Move the logic that uses HttpContext away from the .NET Standard project

Do notice, though, that those classes vary greatly. The .NET Core version was created for ASP.NET Core which is vastly different to ASP.NET 4.5 and olders.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
12

I do not agree with these answers and the non-sense about only having HttpContext in the web project. That is actually tightly coupled as YOU want to be able to re-use code and thus a class library in .net core OR .net standard SHOULD be able to use the HttpContext

So in a .NET Standard you want to add in :

Microsoft.AspNetCore.Http.Abstractions

Sadly though there is so much different about the new HttpContext HttpContext.Current is missing and thus session and request etc..

(Yes, I get the design patterns and why to separate out and make it more testable)

Here is a little trick you can pull off as well to get Current

namespace System.Web
{
    public static class HttpContext
    {
        private static Microsoft.AspNetCore.Http.IHttpContextAccessor m_httpContextAccessor;

        public static void Configure(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor)
        {
            m_httpContextAccessor = httpContextAccessor;
        }


        public static Microsoft.AspNetCore.Http.HttpContext Current
        {
            get
            {
                return m_httpContextAccessor.HttpContext;
            }
        }

    }
}
codeMonkey
  • 4,134
  • 2
  • 31
  • 50
Tom Stickel
  • 19,633
  • 6
  • 111
  • 113
  • 1
    I get null reference exception on calling the `Current` property. Where and how is the best practice to init this? – AleX_ Dec 30 '19 at 21:23
  • same here, while this looks like it should work, I am getting null reference exception on calling the `Current` property as well – Atul Jan 03 '20 at 23:46
  • You need to call `Configure()` before you can call `Current` to give it a context. However, the problem with that is that an HttpContext is different between threads. So, bottom line it appears as if this code is unlikely to work as intended. – Manfred Jan 15 '20 at 03:42
  • @Manfred - I would not have posted it unless it worked for me. – Tom Stickel Jan 21 '20 at 20:10
  • @TomStickel No worries. That's fine. :-) – Manfred Jan 21 '20 at 23:31
  • 1
    Very very neat idea @TomStickel – pim Mar 18 '20 at 11:22
  • As everyone said, Current is null. How to call Configure to set it? – prem Sep 17 '21 at 11:20
  • @prem This worked in 2.x or maybe 1.x - that is when I wrote this answer. That is 2.5 years ago. I don't know at this point. sorry – Tom Stickel Sep 24 '21 at 03:57
4

If you're targetting .NETStandard 2.0 you can work with HttpContext.

Though it is not included in the .NET Standard library, the Microsoft.AspNetCore.Http.Abstractions package (which targets .NET Standard 2.0) will enable you to work with HttpContext.

pim
  • 12,019
  • 6
  • 66
  • 69
2

I need to move this [read cookies and page headers] to a .NET standard library which can be used by both the project...

Do NOT do this.

Let's assume you're performing an operation X on the data you read from the cookies. You may move this operation X to the library instead. The job of the ASP.NET projects is to handle the request pipeline. Reading the cookies belongs there.

galdin
  • 12,411
  • 7
  • 56
  • 71
  • There are many reasons you might want to split out code into specific libraries to share around - this advice is a little short sighted.. – Robert Perry May 25 '23 at 15:53
  • @RobertPerry - unless we're writing a middleware or some library that takes a dependency on ASP.NET, a library should never have to read/manipulate HTTP request/response headers. That belongs in the application layer. The OP's question from 2017 is about sharing code between ASP.NET Core and ASP.NET Classic. – galdin May 26 '23 at 11:54
0

One approach is to have the calling process pass the Http.Current.Request into a method in your Standard class as a parameter of type object. Then use Reflection to access the properties. In your Standard class, something like:

public void ProcessRequest(object Request)
{
    Type oT = Request.GetType();
    string URL = oT.GetProperty("RawUrl").GetValue(Request).ToString();
    // do something
}

Then from your calling application:

oRR.ProcessRequest(HttpContext.Current.Request);

I've tested this from .Net Framework, not from .Net Core. If the context library in Core has different properties, you might need to examine the type returned by GetType to decide which property names to access.

Chuck Bevitt
  • 535
  • 4
  • 13
-1

I agree with the answer above you want to keep netstandard libraries simple and free of web requests if possible. There is a System.Net.Http nuget package that targets .net standard. This could be used when updating 4.6.x up for full framework and for .net core if you are creating a library and do not want the overhead of asp.net core.

Kentonbmax
  • 938
  • 1
  • 10
  • 16
-2

You can create HttpContext.Current before calling your old classes:

using System.Web;
using System.Web.SessionState;

System.Web.HttpContext.Current = new System.Web.HttpContext(new System.Web.HttpRequest("", "http://localhost", ""), new System.Web.HttpResponse(new System.IO.StringWriter()));

System.Web.SessionState.SessionStateUtility.AddHttpSessionStateToContext(
  System.Web.HttpContext.Current,
  new HttpSessionStateContainer("",
    new SessionStateItemCollection(),
    new HttpStaticObjectsCollection(),
    20000,
    true,
    HttpCookieMode.UseCookies,
    SessionStateMode.InProc,
    false
  )
);

HttpContext.Session.SetString("your_session_var", "1");

foreach (string item in HttpContext.Session.Keys)
{
  System.Web.HttpContext.Current.Session[item] = HttpContext.Session.GetString(item);
}

**call your old class library methods

InteXX
  • 6,135
  • 6
  • 43
  • 80