ASP.NET Core中的IUrlHelper注入

63
RC1 中,可以在服务中注入 IUrlHelper (使用启动类中的 services.AddMvc())。
但是在RC2中已经不再适用。有人知道如何在RC2中实现它吗?因为仅仅创建一个UrlHelper对象需要一个ActionContext对象,而在控制器外部获取该对象我并不知道如何实现。
6个回答

85

.NET Core 3+和.NET 5更新(2020年及以后)

按照@Dmitry Pavlov在此线程中的说明,使用LinkGenerator。它可以作为Web框架的一部分注入,并与控制器中已经可用的HttpContext一起使用,或者通过注入IHttpContextAccessor在其他服务中访问。

对于ASP.NET Core RC2,在github仓库上有一个有关此问题的问题。不要注入IUrlHelper,而是采用IUrlHelperFactory。此外,您似乎需要将IActionContextAccessor注入为Controller不再具有公共属性ActionContext

注册依赖项:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

那就依赖它吧:

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

然后按照您的需要使用它。


我不确定该说什么,也许有一个错误——或者 https://github.com/aspnet/Announcements 存储库中有一些内容? - David Pine
1
尽管这是2016年的被接受答案,但像技术中的大多数事物一样,随着时间的推移,事情会发生变化。截至2021年,对于ASP.NET Core 3+和ASP.NET 5,更好的答案是使用LinkGenerator类型,如@Dmitry Pavlov在下面的回答中详细说明的那样。 - Thiago Silva

74

对于 ASP.NET Core 3.x 应用程序,只需要将 IHttpContextAccessorLinkGenerator 注入到您的控制器或服务中。它们应该已经在 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;
        }
    }
}

如果您的应用程序无法解析IHttpContextAccessor,只需将此添加到DI中:

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

1
这种方法的唯一缺点是,您会失去IUrlHelper上的每个定制扩展方法。不幸的是,在这种情况下,您必须依赖于IUrlHelperFactory - T-moty
如果我们有控制器级别的路由值,该方法期望添加它们而不是预填充。你知道任何预填充的方法吗? - Power Star

26

针对 Net Core 2.0

service.AddMvc()之后添加此内容

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

2
我将以下代码添加到我的 Startup.cs 文件中,并将 IUrlHelper 作为 urlHelper 注入到我的标签助手类中。当我调用 urlHelper.Action() 时,它抛出了 IndexOutOfRangeException 异常。 - Bob.at.Indigo.Health

5

针对 .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);
});

1
这同样适用于 .Net Core 6.0。 - Joel Wiklund

3

ASP.NET Core 2.0

安装

PM> Install-Package AspNetCore.IServiceCollection.AddIUrlHelper

使用

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

免责声明: 本软件包作者


6
免责声明:您是该软件包的作者。 - caesay
1
我正在尝试在aspnet signalr core 2.1的Hub中访问IUrlHelper,您的软件包可以使用吗? - Phathutshedzo Khabubu
1
我尝试使用构造函数注入,但是出现了异常,而通过IUrlHelperFactory,操作上下文为空,因此会抛出参数不能为空的异常。 - Phathutshedzo Khabubu
@PhathutshedzoKhabubu,你解决了这个问题吗?我也遇到了同样的问题。 - Mohammed Noureldin
1
@MohammedNoureldin @PhathutshedzoKhabubu IUrlHelper 只能在 HttpContext 内使用。你无法在外部访问它,比如在后台作业中等。 - tchelidze
显示剩余3条评论

0
在ASP.Net Core 2.0中,您不应该注入IUrlHelper。它作为控制器的属性可用。ControllerBase.Url是一个IUrlHelper实例。

2
这并没有回答问题。通常情况下,您不希望在类中对具体控制器进行依赖。 - Stephen
1
同意@Stephen的观点。我想将IUrlHelper注入到一个UI服务中,而这个服务并不依赖于控制器。我的意思是,为什么要依赖呢? - onefootswill
如果我没记错的话,IUrlHelper 的行为取决于当前路由和路由数据。如果直接注入到 UI 服务中,可能会得到令人惊讶的结果。 - Oleksandr Dudnyk
@OleksandrDudnyk 您说得完全正确。我也遇到了这种“惊人”的结果。在类中有没有正确使用IUrlHelper的替代方法? - Mohammad Azhdari
“你说的‘不要注入IUrlHelper’出处在哪里?” - maxbeaudoin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接