Mvc: Can't resolve IHttpContextAccessor, IActionContextAccessor, IUrlHelper in RC2

Created on 15 Jan 2016  路  22Comments  路  Source: aspnet/Mvc

Hello,

I'm currently using the latest RC2 version (build 16854).
I can't inject some MVC special services (IHttpContextAccessor, IActionContextAccessor, IUrlHelper) into my controllers.

I searched but could not find anything about this. Did I misconfigure something? Or if I have to add them as services manually how can I do it?

Most helpful comment

You need to manually register these in your startup code.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

All 22 comments

Is this the proper way?

services.AddScoped<IHttpContextAccessor, HttpContextAccessor>();

And I think for IUrlHelper, I have to create the instance as new UrlHelper(actionContext)?

Why would you need those services in you controller ? The http context and action context are available.

Oh, sorry. Actually I don't need them in my controller. I was just testing them there.

I have a service which needs IUrlHelper to create some urls and another service which is doing a little bit dirty things and needs the controller's name (I was getting it from ActionContext).
I also have a TagHelper using IUrlHelper.

@evorine can you show how you're trying to get the services? Are they constructor parameters of your tag helper?

We had to make IUrlHelper factory-based since it relies on state from the current request. Inject the IUrlHelperFactory instead

Ah indeed, need to depend on IUrlHelperFactory, from which you can get the IUrlHelper.

Closing this for now. If you can show some code that you think should work but doesn't, please let us know.

Hi, I have the same problem. I would like to get access to HttpContext in a class. Injecting IHttpContextAccessor as a constructor parameter no longer works after the upgrade from RC1 to the daily builds. Should it work or is there a new way to get the context?

Same for IActionContextAccessor. We have an auditing class and I would like to get the ActionContext there.

You need to manually register these in your startup code.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

ok great, thank you!

I require IUrlHelper mostly for the Content method and with this change it seems excessive because if I have a request scoped object, I'd need to inject IUrlHelperFactory and IActionContextAccessor just to create an IUrlHelper to access the Content method. I had a look at this method and it uses one single part of the request: Request.PathBase:

if (string.IsNullOrEmpty(path))
    return (string)null;
if ((int)path[0] == 126)
    return requestParts.PathBase.Add(new PathString(path.Substring(1))).Value;
return path;

I've created my own object with this copied logic to inject since it's much lighter so am wondering if maybe even a static method could be created on UrlHelper to contain this logic so we don't have to duplicate it? like:

public static string GetContentPath(string path, PathString requestPathBase)
{
    if (string.IsNullOrEmpty(path))
        return (string)null;
    if ((int)path[0] == 126)
        return requestParts.PathBase.Add(new PathString(path.Substring(1))).Value;
    return path;
}

which could then just be re-used by the non-static Content method?

@Shazwazza at this time that's not a method we're looking to introduce because we're concerned it might add more confusion around which method to call and what to pass in, and I'm not sure it's a particularly common scenario. In the meantime I recommend just having that code in your app (it's only a few lines anyway).

@Eilon no worries, i'll just keep the code in my app, thanks ! :)

@Eilon @rynowak @davidfowl Think it would be a good idea to create an announcement on this (the removal of IHttpContextAccessor etc. by default)? There's quite a few issues popping up, asking why this changed and how to fix it.

When I create a new project from "Web API" template, I can not inject IHttpContextAccessor, but if I create from "Web application" template, I can inject it. What is the difference? Both project has services.AddMvc(); in ConfigureServices method.

@Tratcher can we get an announcement posted for the issue that @khellang mentioned?

Thanks!

:grin::+1:

So, I answer my question: It's registered by Identity (https://github.com/aspnet/Hosting/issues/793#issuecomment-224826052).

@rynowak regarding this post I am just wondering, why it could not be registered AddScoped<>()?

I am short before registering it myself, but want to be sure, I am not doing something realy bad.

@CGollhardt Because it's resolved as a singleton and assigned the HttpContext on each request. That will also let you inject it into your own singletons, while still accessing the HttpContext in request-scope, without capturing a request-scoped dependency.

See https://github.com/aspnet/HttpAbstractions/blob/f152b9863a5651755b8b9fef34e82a888562487e/src/Microsoft.AspNetCore.Http/HttpContextFactory.cs#L38-L42

Also, BTW, in 2.1, there's a helper method, AddHttpContextAccessor, to register the IHttpContextAccessor the correct way:

https://github.com/aspnet/HttpAbstractions/blob/d6a3c3f83e0abb54472f19103bf385ca9d8ead5f/src/Microsoft.AspNetCore.Http/HttpServiceCollectionExtensions.cs#L20-L29

I googled the error that comes up and nothing came up, but found this thread via other means.

I'm including the original error so hopefully someone else Googling for this finds the answer:

System.InvalidOperationException: Cannot resolve 'Microsoft.AspNetCore.Http.IHttpContextFactory' from root provider because it requires scoped service 'Microsoft.AspNetCore.Http.IHttpContextAccessor'.

I originally had this line:

services.TryAddScoped<IHttpContextAccessor, HttpContextAccessor>();

I replaced it with:

services.AddHttpContextAccessor();

And that resolved the issue.

I'm going to open an issue on the 2.0 -> 2.1 migration page, this should be in the documentation. (Issue now opened here.)

Was this page helpful?
0 / 5 - 0 ratings