23

My data service layer in my API required information that are of the request in the httpcontext, I read this question and they said that I should used the ActionContext instead of HttpContext.Current (discontinue in MVC6).

The first way is to set the data inside the controller by overriding this method:

public void OnActionExecuting(ActionExecutingContext context)
{
    var routeData = context.RouteData;
    var httpContext = context.HttpContext;
    ...
}

Or using DI by injecting into the service layer

public MyService(IContextAccessor<ActionContext> contextAccessor)
{
    _httpContext = contextAccessor.Value.HttpContext;
    _routeData = contextAccessor.Value.RouteData;
}

but I'm not sure with of the both line of code listed below is correct way to do the DI

services.AddTransient<IContextAccessor<ActionContext>,ContextAccessor>();
services.AddTransient<IContextAccessor<ActionContext>>();

when I do this I get this error.

Unable to resolve service for type 'Microsoft.AspNet.Mvc.ActionContext' while attempting to activate

Update project.json web project

"DIMultiTenan.Infrastructure": "",
"DIMultiTenan.MongoImplementation": "", 
"Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
"Microsoft.AspNet.Mvc": "6.0.0-beta3",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta3",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta3"
Community
  • 1
  • 1
Son_of_Sam
  • 1,913
  • 2
  • 22
  • 37
  • 1
    remove the 1st line and retry – agua from mars Mar 10 '15 at 17:49
  • 1
    Apologies for the confusion but I try the code one line at the time – Son_of_Sam Mar 10 '15 at 17:54
  • 1
    did you try with AddScopped instead AddTransient ? – agua from mars Mar 10 '15 at 18:42
  • 1
    By the way, are you using Beta3 or latest dev code. – Kiran Mar 10 '15 at 18:44
  • 1
    see update question I added the project.json file for the web project. I'm using vs2015 CTP 6 – Son_of_Sam Mar 10 '15 at 18:49
  • I am not sure about Beta3 but in latest non-released versions, you can use `IHttpContextAccessor` for this purpose. Example: https://github.com/aspnet/Mvc/blob/dev/test/WebSites/ControllersFromServicesClassLibrary/QueryValueService.cs#L13 ...and you would register the `QueryValueService` to be a Transient or Scoped...Note that you should not register QueryValueService as Singleton as HttpContext is per-request based... – Kiran Mar 10 '15 at 19:30
  • @KiranChalla I did this, please tell me if I did something worng services.AddTransient(); – Son_of_Sam Mar 10 '15 at 19:47
  • @Son_of_Sam: you need not do that...you can check the links posted in my answer...also i noticed that `IHttpContextAccessor` is available in Beta3, so you should be able to use it.. – Kiran Mar 10 '15 at 20:14

1 Answers1

46

If you are trying to access HttpContext, then you can use IHttpContextAccessor for this purpose.

Example:

services.AddTransient<QueryValueService>();

public class QueryValueService
{
    private readonly IHttpContextAccessor _accessor;

    public QueryValueService(IHttpContextAccessor httpContextAccessor)
    {
        _accessor = httpContextAccessor;
    }

    public string GetValue()
    {
        return _accessor.HttpContext.Request.Query["value"];
    }
}

Note that in the above example QueryValueService should be registered only as Transient or Scoped and not Singleton as HttpContext is per-request based...

Steven
  • 166,672
  • 24
  • 332
  • 435
Kiran
  • 56,921
  • 15
  • 176
  • 161
  • 1
    your QueryValueService only get query information in my case i need information from the header request collection. But thanks for the help – Son_of_Sam Mar 10 '15 at 20:25
  • 1
    @Son_of_Sam: That was just an example :-), sure you can get the header information too from the request present on the context. – Kiran Mar 10 '15 at 20:31
  • 1
    I made a small (but important change) to the code. I moved the call to `.HttpContext` out of the constructor. This is important because [injection constructors should be simple](http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/). The call made it possible for the constructor to fail and made it much harder to verify object graphs. – Steven May 05 '15 at 15:50
  • 1
    @Steven if that the case, where you put the scenario where you inject a factory that produce a repository and you want just the repository, in the ctor you will set the IReposotory using a factory method. – Son_of_Sam Jun 05 '15 at 14:10
  • 1
    @Son_of_Sam: That seems like an invalid use case. Instead of calling the factory inside the constructor, just inject the repository into the constructor. – Steven Jun 05 '15 at 14:24
  • 2
    @steve, this is a question that I ask regarding what I'm trying to do http://stackoverflow.com/questions/29113206/change-injected-object-at-runtime, I will apriciate your input, after this I will buy you a cup coffee – Son_of_Sam Jun 05 '15 at 14:49
  • 1
    You need to inject the `IHttpContextAccessor` now: `services.AddSingleton();` – jasdefer Aug 23 '16 at 11:37