61

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.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
RolandG
  • 1,269
  • 4
  • 14
  • 21

6 Answers6

82

.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.

Thiago Silva
  • 14,183
  • 3
  • 36
  • 46
David Pine
  • 23,787
  • 10
  • 79
  • 107
  • I'm not sure what to say, perhaps there is a bug - otherwise there might be something in the https://github.com/aspnet/Announcements repo? – David Pine Jun 18 '18 at 12:06
  • 1
    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. – Thiago Silva Apr 08 '21 at 14:08
73

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();
}
Dmitry Pavlov
  • 30,789
  • 8
  • 97
  • 121
  • 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` – T-moty Apr 17 '21 at 17:46
  • If we have controller level route value, this method expects to add them instead prefill. Do you know anyway to prefill it. – Power Star Mar 08 '22 at 13:11
26

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);
});
smn.tino
  • 2,272
  • 4
  • 32
  • 41
frostymarvelous
  • 2,786
  • 32
  • 43
  • 2
    Added this code to my `Startup.cs`, injected IUrlHelper into my tag helper class as `urlHelper`. When I call `urlHelper.Action()` it throws `IndexOutOfRangeException`. – Bob.at.Indigo.Health Aug 23 '19 at 00:12
5

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);
});
Dilhan Jayathilake
  • 1,860
  • 2
  • 17
  • 15
2

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

tchelidze
  • 8,050
  • 1
  • 29
  • 49
  • 6
    Disclaimer: You are the author of this package – caesay Oct 31 '17 at 00:24
  • 1
    I am trying to access IUrlHelper on a Hub in aspnet signalr core 2.1 will your package work? – Phathutshedzo Khabubu May 24 '18 at 14:58
  • @PhathutshedzoKhabubu package just registers `IUrlHelper` in `ServiceCollection` with necessary dependencies. As far as `DI` is available, `IUrlHelper` will also be available. – tchelidze May 25 '18 at 06:29
  • 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()` – Phathutshedzo Khabubu May 25 '18 at 12:08
  • @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` – tchelidze May 25 '18 at 12:22
  • 1
    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 – Phathutshedzo Khabubu May 25 '18 at 20:59
  • @PhathutshedzoKhabubu, have you solved the issue? I have the same problem – Mohammed Noureldin Jun 18 '18 at 09:57
  • 1
    @MohammedNoureldin @PhathutshedzoKhabubu `IUrlHepler` is only available inside HttpContext. You can't access it outside, let's say in a background job, etc. – tchelidze Jun 18 '18 at 10:10
0

For ASP.Net Core 2.0 you must not inject an IUrlHelper. It’s available as a property of the controller. ControllerBase.Url is an IUrlHelper instance.

  • 2
    This doesn't answer the question. Often you don't want to take a dependency on a concrete controller in a class. – Stephen Apr 18 '19 at 00:15
  • 1
    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? – onefootswill Apr 23 '19 at 01:01
  • 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. – Oleksandr Dudnyk May 01 '19 at 13:43
  • @OleksandrDudnyk you're absolutely right. I've faced this "surprising" result. Is there any alternative for IUrlHelper to use correctly in a class? – Mohammad Azhdari May 16 '19 at 08:01
  • What's your source on "you must not inject and IUrlHelper"? – maxbeaudoin Oct 25 '19 at 20:49