user10189172
user10189172

Reputation:

Asp.Net Core 2.x HttpContext.Current not really available

I am not seeing much information on porting a asp.net mvc 4.6 application to the asp.net core 2.1 Tons of 1.0 to 2.0 and 2.0. to 2.1 articles, but it is a bit steep in changes.

Ok, I have been all over google and stackoverflow and what I am trying/wanting to do is convert an older .net application and bring it into .net core.

Some big culprits I see as problems are the following:

HttpContext.Current
HttpContext.Current.Request.Url.AbsolutePath
HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)
private static string CollectionToHtmlTable(HttpCookieCollection collection)

I was seeing these articles which are helpful, but much to be desired.

https://www.carlrippon.com/httpcontext-in-asp-net-core/ https://dotnetcoretutorials.com/2017/01/05/accessing-httpcontext-asp-net-core/

Inside Controller it seems the easiest, but most of this HttpContext.Current stuff is sprinkled around various places domain libraries etc..

So in both url's above it seems that using this line below in the startup.cs however, I don't have a startup.cs outside of main asp.net core

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

Then also in startup I seen this article https://www.strathweb.com/2016/12/accessing-httpcontext-outside-of-framework-components-in-asp-net-core/

//one of many things added to project
services.AddHttpContextAccessor();

I realize that several questions have been asked in the last couple of years - here is to hoping that some brave soul has explored this stuff and has some advise/answers to how to migrate this stuff over.

Method to Port: #1

  public Service(string key, LogRecord.CallType callType, string operation, string opArg, string opResponse)
    {
        this.Key = string.IsNullOrEmpty(key)
                       ? HttpContext.Current != null ? "Inbound/WebHttp: " + HttpContext.Current.Request.Url.AbsolutePath : string.Empty
                       : key;
        this.CallType = Enum.GetName(typeof(LogRecord.CallType), callType);
        this.URL = HttpContext.Current != null && callType == LogRecord.CallType.WebHttp
                       ? HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)
                       : string.Empty;
        this.Operation = operation;
        this.OpArg = opArg;
        this.OpResponse = opResponse;
    }

Another: #2

   private static string CollectionToHtmlTable(HttpCookieCollection collection)
    {
        // Converts HttpCookieCollection to NameValueCollection
        var nvc = new NameValueCollection();
        foreach (string item in collection)
        {
            var httpCookie = collection[item];
            if (httpCookie != null)
            {
                nvc.Add(item, httpCookie.Value);
            }
        }

        return CollectionToHtmlTable(nvc);
    }

Upvotes: 3

Views: 9161

Answers (2)

Christian Gollhardt
Christian Gollhardt

Reputation: 17004

The problem is, you are currently using it wrong.

Inside Controller it seems the easiest, but most of this HttpContext.Current stuff is sprinkled around various places domain libraries etc..

A Domain Libarary should be independent from the frontend. It just doesn't matter if it's a website with Session or a statefull WPF App. Or a RestFull Api.

That said, a relative Quick Fix would be to inject the HttpContext into your domain class.

public DomainService(IHttpContextAccessor httpContext)
{
    _httpContext = httpContext;
}

You can then obtain your DomainService via Dependency Injection. If the creation is complex, you are looking for a Factory.

Or you could create the Service yourself in your ActionMethod (Of course in this case you need need to change the constructor of the Service to HttpContext:

public IActionResult Foo()
{
    var service = new DomainService(HttpContext)
}

That said: it was removed for a reason. Please do not rely on HttpContext in your Domain! Create a business object and give it as parameter to the domain instead.


Not sure if it is the best way, but I have created a BusinessContext class and registered it as scoped. A factory is responsible for creating it with the needed data.


DON'T DO THIS:

If you are really crazy, maybe this could help you for migration.

Upvotes: 5

ProgrammingLlama
ProgrammingLlama

Reputation: 38767

Posting this on request of OP, so it's not a full answer. You can reconstruct the URI from the IHttpContextAccessor like so:

IHttpContextAccessor context; // injected
var request = context.HttpContext.Request;

var uriBuilder = new UriBuilder();
uriBuilder.Scheme = request.Scheme;
uriBuilder.Host = request.Host.Host;
if (request.Host.Port.HasValue)
{
    uriBuilder.Port = request.Host.Port.Value;
}
uriBuilder.Path = request.Path;
if (request.QueryString.HasValue)
{
    uriBuilder.Query = request.QueryString.Value.Substring(1);
}

var requestUri = uriBuilder.Uri;

Likewise, you can access the IRequestCookieCollection via:

var collection = context.HttpContext.Request.Cookies
foreach (KeyValuePair<string, string> cookie in collection)

Upvotes: 2

Related Questions