【问题标题】:Unable to utilize UrlHelper无法使用 UrlHelper
【发布时间】:2015-06-07 17:18:20
【问题描述】:

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

以前使用 UrlHelper 非常简单:

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

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

【问题讨论】:

    标签: asp.net asp.net-core-mvc


    【解决方案1】:

    更新 - 发布 RC2

    正如@deebo 提到的,您不再可以直接从 DI 获得IUrlHelper。相反,您需要将IUrlHelperFactoryIActionContextAccessor 注入您的类并使用它们来获取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 将为空)


    我已使用HttpContext.RequestServices 中的IServiceProvider 检索到IUrlHelper

    通常你手头会有一个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;
    }
    

    【讨论】:

    • facepalm 我不知道我可以通过依赖注入获得一个 url 助手,因为我认为这是必须添加到服务中的东西。跨度>
    【解决方案2】:

    我想我会为即将到来的 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

    【讨论】:

    • 除了您提到的在启动配置中注册 IUrlHelper 之外,我不确定我是否理解它现在与原始解决方案有何不同或如何不同?一个更好的问题是为什么我需要先注册它。现在似乎还有很多工作。
    • 唯一的区别是它应该在 RC2 中工作。目前的答案是正确的。我在搞乱 RC2 并遇到了链接的博客文章中描述的问题。还提到了这个链接 git commit github.com/aspnet/Mvc/commit/… 似乎表明设计决定删除对 IActionContextAccessor 的依赖。也许@davidfowl 或 aspnet 团队的其他人可以解释一下
    【解决方案3】:

    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();
    

    【讨论】:

    • 为什么 UrlHelper 是作用域的?
    • @IvanMontilla 好问题。原因是它需要当前的ActionContext 才能运行。
    【解决方案4】:

    如果你像我一样只需要UrlHelper.Link 方法,你甚至不需要UrlHelper,只需使用Url.Link

    【讨论】:

      【解决方案5】:

      没有构建特殊工厂类的较短版本

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 2011-08-10
        • 1970-01-01
        相关资源
        最近更新 更多