无法使用UrlHelper

问题描述 投票:0回答:6

我目前正在尝试做一些在 ASP.NET 4 中非常简单直接的事情,但现在在 ASP.NET 5 中情况并非如此。

以前使用 UrlHelper 非常简单:

var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

但是我一生都无法思考如何使用新的 UrlHelper。我正在查看测试用例,要么我完全愚蠢,要么我错过了一些东西,但我似乎无法弄清楚。任何帮助解决这个问题的帮助都会很棒。

asp.net asp.net-core-mvc
6个回答
21
投票

更新 - RC2 后

正如 @deebo 提到的,您不再可以直接从 DI 获得

IUrlHelper
。相反,您需要将
IUrlHelperFactory
IActionContextAccessor
注入到您的类中,并使用它们来获取
IUrlHelper
实例,如下所示:

public MyClass(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionAccessor)
{
    this.urlHelperFactory = urlHelperFactory;
    this.actionAccessor = actionAccessor;
}

public void SomeMethod()
{
    var urlHelper = this.urlHelperFactory.GetUrlHelper(this.actionAccessor.ActionContext);
}

您还需要在启动类中注册(

IUrlHelperFactory
已默认注册):

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

请记住,只有当您获取 actionContext 的代码在 MVC/路由中间件之后运行时,这才有效! (否则

actionAccessor.ActionContext
将为空)


我已经使用

IUrlHelper
中的
IServiceProvider
检索了
HttpContext.RequestServices

通常您手头会有

HttpContext
房产:

  • 在控制器操作方法中,您可以执行以下操作:

    var urlHelper = this.Context.RequestServices.GetRequiredService<IUrlHelper>();
    ViewBag.Url = urlHelper.Action("Contact", "Home", new { foo = 1 });
    
  • 在过滤器中您可以执行以下操作:

    public void OnActionExecuted(ActionExecutedContext context)
    {
        var urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
        var actionUrl = urlHelper.Action("Contact", "Home", new { foo = 1 });
        //use actionUrl ...
    }
    

另一种选择是利用内置的依赖注入,例如您的控制器可以有一个如下所示的构造函数,并且在运行时将提供一个

IUrlHelper
实例:

private IUrlHelper _urlHelper;
public HomeController(IUrlHelper urlHelper)
{
    _urlHelper = urlHelper;
}

15
投票

我想分享即将到来的 RC2,因为当前的答案将不再有效。

从 RC 2 开始,您将需要显式注册 IActionContextAccessorIUrlHelperFactory

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();

然后使用 DI/服务定位器:

public EmailTagHelper(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
  _urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
}

我在这里写了关于 TagHelpers 的博客:http://devonburriss.me/asp-net-5-tips-urlhelper


5
投票

Startup.cs

   services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
   services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();
   services.AddScoped(it => it.GetService<IUrlHelperFactory>()
                    .GetUrlHelper(it.GetService<IActionContextAccessor>().ActionContext));

或者

PM> Install-Package AspNetCore.IServiceCollection.AddIUrlHelper 

Startup.cs

services.AddUrlHelper();

2
投票

如果你像我一样只需要

UrlHelper.Link
方法,你甚至不再需要
UrlHelper
,只需使用
Url.Link


1
投票

无需构建特殊工厂类的较短版本

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
            .AddScoped<IUrlHelper>(sp => new UrlHelper(sp.GetRequiredService<IActionContextAccessor>().ActionContext));

0
投票

例如,当您在 .NET 8 中使用

UseEndpoints
时,您可能会收到以下错误

找不到与 ActionContext 关联的 IRouter。如果您的应用程序使用端点路由,那么您可以获取具有依赖项注入的 IUrlHelperFactory 并使用它来创建 UrlHelper,或使用 Microsoft.AspNetCore.Routing.LinkGenerator。

错误消息非常清楚,但这就是我解决它的方法

serviceCollection.TryAddSingleton<Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor, Microsoft.AspNetCore.Mvc.Infrastructure.ActionContextAccessor>();
serviceCollection.TryAddScoped<Microsoft.AspNetCore.Mvc.IUrlHelper>(serviceProvider =>
{
    var actionContext = serviceProvider.GetRequiredService<Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor>().ActionContext!;

    return serviceProvider.GetRequiredService<Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory>().GetUrlHelper(actionContext);
});

然后您可以稍后在控制器中检索它,如下所示

 var urlHelper = HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
© www.soinside.com 2019 - 2024. All rights reserved.