Injection of IUrlHelper in ASP.NET Core
Asked Answered
P

6

66

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.

Proser answered 19/5, 2016 at 11:38 Comment(0)
O
88

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

Ona answered 19/5, 2016 at 11:49 Comment(2)
I'm not sure what to say, perhaps there is a bug - otherwise there might be something in the github.com/aspnet/Announcements repo?Ona
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.Erasmo
J
77

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();
}
Jaynajayne answered 17/1, 2020 at 16:35 Comment(2)
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 IUrlHelperFactoryRoryros
If we have controller level route value, this method expects to add them instead prefill. Do you know anyway to prefill it.Neigh
W
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);
});
Weslee answered 2/3, 2018 at 6:27 Comment(1)
Added this code to my Startup.cs, injected IUrlHelper into my tag helper class as urlHelper. When I call urlHelper.Action() it throws IndexOutOfRangeException.Wack
F
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);
});
Floeter answered 14/7, 2018 at 11:20 Comment(1)
This works for .Net Core 6.0 as well.Analyzer
C
3

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

Conversation answered 18/10, 2017 at 7:28 Comment(8)
Disclaimer: You are the author of this packageOutshine
I am trying to access IUrlHelper on a Hub in aspnet signalr core 2.1 will your package work?Amarillis
@PhathutshedzoKhabubu package just registers IUrlHelper in ServiceCollection with necessary dependencies. As far as DI is available, IUrlHelper will also be available.Conversation
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()Amarillis
@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 nullConversation
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 nullAmarillis
@PhathutshedzoKhabubu, have you solved the issue? I have the same problemParamnesia
@MohammedNoureldin @PhathutshedzoKhabubu IUrlHepler is only available inside HttpContext. You can't access it outside, let's say in a background job, etc.Conversation
K
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.

Keramics answered 23/1, 2019 at 12:48 Comment(5)
This doesn't answer the question. Often you don't want to take a dependency on a concrete controller in a class.Froebel
Agree with @Froebel . I want to inject the IUrlHelper into a Ui Service which has no dependency on a controller. I mean, why would it?Sustain
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.Keramics
@OleksandrDudnyk you're absolutely right. I've faced this "surprising" result. Is there any alternative for IUrlHelper to use correctly in a class?Pickings
What's your source on "you must not inject and IUrlHelper"?Margret

© 2022 - 2024 — McMap. All rights reserved.