MVC 6 IUrlHelper Dependency Injection
Asked Answered
E

4

12

I want to use IUrlHelper through dependency injection to be able to use its functionality to generate uris for different rest endpoints. I cant seem how to figure out how to create a UrlHelper from scratch because it changed in MVC 6 and MVC doesnt automatically have that service available in the IoC controller.

The setup is my Controller take in an internal model to api model converter class and that uses the IUrlHelper (all through Depenedency Injection).

If there is a better alternative to IUrlHelper/UrlHelper I can use to generate Uris for my WebApi action/controllers I am open to suggestion.

Exsiccate answered 25/6, 2015 at 19:48 Comment(5)
Is there an option you could wrapper the exiting UrlHelper, for example IUrlWrapper, then use the wrapper instead?Mass
I would need the urlhelper still correct? How would that be differentExsiccate
Yes I can't think of a way you would not avoid a UrlHelper. From DI point of view, you need to create a wrapper as I mention before.Mass
I guess im not understanding. How am I suppose to wrap the UrlHelper if I dont know how to get it.Exsiccate
Does this answer your question? Injection of IUrlHelper in ASP.NET CoreCappello
E
8

This method is now obsolete. Look at update below.

Instead of services.AddTransient<IUrlHelper, UrlHelper>() or trying to directly inject IUrlHelper you can inject IHttpContextAccessor and get the service from there.

public ClassConstructor(IHttpContextAccessor contextAccessor)
{
    this.urlHelper = contextAccessor.HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
}

Unless it is just a bug, adding the IUrlHelper service with UrlHelper does not work.

UPDATE 2017-08-28

The previous method no longer seems to work. Below is a new solution.

Confgure IActionContextAccessor as a service:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddSingleton<IActionContextAccessor, ActionContextAccessor>()
        .AddMvc();
}

Then inject IActionContextAccessor and IUrlHelperFactory to then generate the IUrlHelper like below

public class MainController : Controller
{
    private IUrlHelperFactory urlHelperFactory { get; }
    private IActionContextAccessor accessor { get; }
    public MainController(IUrlHelperFactory urlHelper, IActionContextAccessor accessor)
    {
        this.urlHelperFactory = urlHelper;
        this.accessor = accessor;
    }

    [HttpGet]
    public IActionResult Index()
    {
        ActionContext context = this.accessor.ActionContext;
        IUrlHelper urlHelper = this.urlHelperFactory.GetUrlHelper(context);
        //Use urlHelper here
        return this.Ok();
    }
}
Exsiccate answered 13/7, 2015 at 18:49 Comment(3)
No component for supporting the service Microsoft.AspNetCore.Mvc.IUrlHelper was found'Irishman
@Irishman this may no longer apply. This was before initial release and now there is aspnet core 2. Not sure what version you are usingExsiccate
using .net core 1.1Irishman
O
14

The UrlHelper requires the current action context, and we can acquire that from the ActionContextAccessor. I'm using this:

        services.AddScoped<IActionContextAccessor, ActionContextAccessor>();
        services.AddScoped<IUrlHelper>(x =>
        {
            var  actionContext = x.GetService<IActionContextAccessor>().ActionContext;
            return new UrlHelper(actionContext);
        });

Now, you can inject IUrlHelper directly into anything that needs it without having to jump through IHttpContextAccessor .

Organotherapy answered 1/11, 2016 at 10:35 Comment(2)
This is great, because I need the UrlHelper in a service that has to be injected into the controller, so it needs to happen before I'm in the controller. Nice solution.Pragmatic
This works on .net core 2.2, but I had to change IActionContextAccessor to be AddTransient instead of AddScoped due to using IUrlHelper.RouteUrl in my consuming classRisley
E
8

This method is now obsolete. Look at update below.

Instead of services.AddTransient<IUrlHelper, UrlHelper>() or trying to directly inject IUrlHelper you can inject IHttpContextAccessor and get the service from there.

public ClassConstructor(IHttpContextAccessor contextAccessor)
{
    this.urlHelper = contextAccessor.HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
}

Unless it is just a bug, adding the IUrlHelper service with UrlHelper does not work.

UPDATE 2017-08-28

The previous method no longer seems to work. Below is a new solution.

Confgure IActionContextAccessor as a service:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddSingleton<IActionContextAccessor, ActionContextAccessor>()
        .AddMvc();
}

Then inject IActionContextAccessor and IUrlHelperFactory to then generate the IUrlHelper like below

public class MainController : Controller
{
    private IUrlHelperFactory urlHelperFactory { get; }
    private IActionContextAccessor accessor { get; }
    public MainController(IUrlHelperFactory urlHelper, IActionContextAccessor accessor)
    {
        this.urlHelperFactory = urlHelper;
        this.accessor = accessor;
    }

    [HttpGet]
    public IActionResult Index()
    {
        ActionContext context = this.accessor.ActionContext;
        IUrlHelper urlHelper = this.urlHelperFactory.GetUrlHelper(context);
        //Use urlHelper here
        return this.Ok();
    }
}
Exsiccate answered 13/7, 2015 at 18:49 Comment(3)
No component for supporting the service Microsoft.AspNetCore.Mvc.IUrlHelper was found'Irishman
@Irishman this may no longer apply. This was before initial release and now there is aspnet core 2. Not sure what version you are usingExsiccate
using .net core 1.1Irishman
I
1

ASP.NET Core 2.0

Install

PM> Install-Package AspNetCore.IServiceCollection.AddIUrlHelper

Use

public void ConfigureServices(IServiceCollection services)
{
   ... 
   services.AddUrlHelper();
   ... 
}

Disclaimer: author of this package

Irishman answered 18/1, 2018 at 22:1 Comment(0)
A
0

FOR .NET CORE 3.1

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
                .AddScoped(x =>
                    x.GetRequiredService<IUrlHelperFactory>()
                        .GetUrlHelper(x.GetRequiredService<IActionContextAccessor>().ActionContext)); //Inject UrlHelp for
Atwekk answered 13/2, 2021 at 23:1 Comment(1)
Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotesNashbar

© 2022 - 2024 — McMap. All rights reserved.