Injection of IUrlHelper in ASP.NET Core

23,609

Solution 1

.NET Core 3+ and .NET 5 Update (2020 and later)

Use LinkGenerator as detailed in @Dmitry Pavlov's answer on this thread. It's injectable as part of the web framework, and works with the HttpContext already available in controllers, or accessible in other services by injecting the IHttpContextAccessor.

For ASP.NET Core RC2 there is an issue for this on the github repo. Instead of injecting the IUrlHelper, take an IUrlHelperFactory. It also sounds like you'd need the IActionContextAccessor injected as a Controller no longer has a public property ActionContext.

Register the dependency:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

Then depend on it:

public SomeService(IUrlHelperFactory urlHelperFactory,
                   IActionContextAccessor actionContextAccessor)
{
 
    var urlHelper =
        urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
}

Then use it as you see fit.

Solution 2

For ASP.NET Core 3.x app just inject IHttpContextAccessor and LinkGenerator to your controller or service. They should be already available in DI.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;

namespace Coding-Machine.NET
{
    public class MyService
    {
        private readonly IHttpContextAccessor _accessor;
        private readonly LinkGenerator _generator;

        public MyService(IHttpContextAccessor accessor, LinkGenerator generator)
        {
            _accessor = accessor;
            _generator = generator;
        }

        private string GenerateConfirmEmailLink()
        {
            var callbackLink = _generator.GetUriByPage(_accessor.HttpContext,
                page: "/Account/ConfirmEmail",
                handler: null, 
                values: new {area = "Identity", userId = 123, code = "ASDF1234"});

            return callbackLink;
        }
    }
}

If your app can't resolve IHttpContextAccessor just add this to DI:

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

Solution 3

For Net Core 2.0

Add this after service.AddMvc()

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

Solution 4

For .Net Core 2.0

services.AddMvc();

services.AddScoped<IUrlHelper>(x =>
{
   var actionContext = x.GetRequiredService<IActionContextAccessor>().ActionContext;
   var factory = x.GetRequiredService<IUrlHelperFactory>();
   return factory.GetUrlHelper(actionContext);
});

Solution 5

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

Share:
23,609
RolandG
Author by

RolandG

Updated on April 09, 2021

Comments

  • RolandG
    RolandG about 3 years

    In RC1, IUrlHelper could be injected in services (with services.AddMvc() in startup class)

    This doesn't work anymore in RC2. Does anybody know how to do it in RC2 as just newing up a UrlHelper requires an ActionContext object. Don't know how to get that outside a controller.

  • caesay
    caesay over 6 years
    Disclaimer: You are the author of this package
  • Phathutshedzo Khabubu
    Phathutshedzo Khabubu almost 6 years
    I am trying to access IUrlHelper on a Hub in aspnet signalr core 2.1 will your package work?
  • tchelidze
    tchelidze almost 6 years
    @PhathutshedzoKhabubu package just registers IUrlHelper in ServiceCollection with necessary dependencies. As far as DI is available, IUrlHelper will also be available.
  • Phathutshedzo Khabubu
    Phathutshedzo Khabubu almost 6 years
    I installed this package in an asp,net core 2.0.6 application and tried injecting the IUrlHelper in a singnalR Core Hub but it was not injected and got back null so thats way I raised that and note I added services.AddUrlHelper(); after services.AddMvc()
  • tchelidze
    tchelidze almost 6 years
    @PhathutshedzoKhabubu How are you accessing IUrlHelper ? if you're injecting it into constructor and it's not available, then you'll get exception instead of null
  • Phathutshedzo Khabubu
    Phathutshedzo Khabubu almost 6 years
    I tried via constructor injection than I got an exception but Via IUrlHelperFactory the action context is null therefore it throws an exception that the argument can not be null
  • Mohammed Noureldin
    Mohammed Noureldin almost 6 years
    @PhathutshedzoKhabubu, have you solved the issue? I have the same problem
  • tchelidze
    tchelidze almost 6 years
    @MohammedNoureldin @PhathutshedzoKhabubu IUrlHepler is only available inside HttpContext. You can't access it outside, let's say in a background job, etc.
  • David Pine
    David Pine almost 6 years
    I'm not sure what to say, perhaps there is a bug - otherwise there might be something in the github.com/aspnet/Announcements repo?
  • Stephen
    Stephen about 5 years
    This doesn't answer the question. Often you don't want to take a dependency on a concrete controller in a class.
  • onefootswill
    onefootswill about 5 years
    Agree with @Stephen . I want to inject the IUrlHelper into a Ui Service which has no dependency on a controller. I mean, why would it?
  • Oleksandr Dudnyk
    Oleksandr Dudnyk about 5 years
    If I'm not mistaken the behavior of IUrlHelper depends on current Route and RouteData. In the case of direct injecting into Ui Service you may end up with surprising results.
  • Mohammad Azhdari
    Mohammad Azhdari almost 5 years
    @OleksandrDudnyk you're absolutely right. I've faced this "surprising" result. Is there any alternative for IUrlHelper to use correctly in a class?
  • Bob.at.Indigo.Health
    Bob.at.Indigo.Health over 4 years
    Added this code to my Startup.cs, injected IUrlHelper into my tag helper class as urlHelper. When I call urlHelper.Action() it throws IndexOutOfRangeException.
  • maxbeaudoin
    maxbeaudoin over 4 years
    What's your source on "you must not inject and IUrlHelper"?
  • user510101
    user510101 about 3 years
    though this is the accepted answer from 2016, as with most things in tech, things change with time. As of 2021, the better answer for ASP.NET Core 3+ and ASP.NET 5 is to use the LinkGenerator type as detailed in @Dmitry Pavlov's answer below.
  • T-moty
    T-moty about 3 years
    The only downside of this approach is that you lose every custom-made extension method on IUrlHelper. Sadly in that case you have to rely on IUrlHelperFactory
  • Power Star
    Power Star about 2 years
    If we have controller level route value, this method expects to add them instead prefill. Do you know anyway to prefill it.