【问题标题】:How to add the slug to all Link generation in an asp.net core website?如何将 slug 添加到 asp.net 核心网站中的所有链接生成?
【发布时间】:2019-07-10 19:11:18
【问题描述】:

我需要能够控制由我的Url.Content("~") 调用生成的链接,以便能够在链接的开头接受一个 Slug。基本上,托管 URL 将位于负载均衡器之后,并且可能位于根级别或位于更友好的 URL 之后...

例如: 站点配置为在http://localhost:5001下运行,所以Url.Content("~/scripts/site.js")会生成"/scripts/site.js"

如果浏览器直接访问该 url 或什至是 www.mysite.com 之类的别名,这很好。

但我希望能够灵活地在 www.mysite.com/Slug 下托管网站(想想证书等)......

现在我生成的链接转到 www.mysite.com/scripts.site.js 解析为 404。

理想情况下,可以在自定义 IUrlHelper 甚至自定义 LinkGenerator 中配置 slug,但我似乎无法注入这些并覆盖当前的。

我试过了:

services.AddScoped<IUrlHelper>(x =>
            {
                var actionContext = x.GetService<IActionContextAccessor>().ActionContext;
                return new MyCustomUrlHelper(actionContext);
            });

但无法注入。当我尝试调试时,我注意到如果你在控制器中调用相同的命令,你会得到一个 Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper 的实例。

有没有办法在不创建自定义帮助器的情况下改变它(因为在某些区域会遗漏它并且会使调试几乎不可能找到被滥用的帮助器)

【问题讨论】:

    标签: c# asp.net-core-mvc slug urlhelper


    【解决方案1】:

    直接绑定 IUrlHelper 无效,因为 MVC 在内部使用工厂解析实例。要在控制器和 razor 视图中获取您自己的自定义 URL 帮助器的实例,您需要在启动类中提供 IUrlHelperFactory 的自定义实现。

    以下代码 sn-ps 允许您使用自己的功能装饰原始 URL 助手:

    在您的Startup 类中,您需要为IUrlHelperFactory 添加具有单例范围的自定义实现之后 AddMvc:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddSingleton<IUrlHelperFactory, CustomUrlHelperFactory>();
    }
    

    自定义实现可能如下所示:

    public class CustomUrlHelper : IUrlHelper
    {
        private IUrlHelper _originalUrlHelper;
    
        public ActionContext ActionContext { get; private set; }
    
        public CustomUrlHelper(ActionContext actionContext, IUrlHelper originalUrlHelper)
        {
            this.ActionContext = actionContext;
            this._originalUrlHelper = originalUrlHelper;
        }
    
        public string Action(UrlActionContext urlActionContext)
        {
            return _originalUrlHelper.Action(urlActionContext);
        }
    
        public string Content(string contentPath)
        {
            return _originalUrlHelper.Content(contentPath);
        }
    
        public bool IsLocalUrl(string url)
        {
            return _originalUrlHelper.IsLocalUrl(url);
        }
    
        public string Link(string routeName, object values)
        {
            return _originalUrlHelper.Link(routeName, values);
        }
    
        public string RouteUrl(UrlRouteContext routeContext)
        {
            return _originalUrlHelper.RouteUrl(routeContext);
        }
    }
    
    public class CustomUrlHelperFactory : IUrlHelperFactory
    {
        public IUrlHelper GetUrlHelper(ActionContext context)
        {
            var originalUrlHelperFactory = new UrlHelperFactory();
            var originalUrlHelper = originalUrlHelperFactory.GetUrlHelper(context);
            return new CustomUrlHelper(context, originalUrlHelper);
        }
    }
    

    【讨论】:

    • 谢谢,这正是我们所需要的。我能够在 UrlHelperFactory 中使用我原来的 UrlHelper。
    【解决方案2】:

    默认情况下 IUrlHelper 是不可注入的。

    您必须将您的 startup.cs 代码稍微修改为explained in this blog.

    您必须先注册 IActionContextAccessor。

    然后在 UrlHelperFactory 的帮助下,您可以注入您的自定义实现,如下所示:

    services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
    services.AddScoped<IUrlHelper>(x => {
        var actionContext = x.GetRequiredService<IActionContextAccessor>().ActionContext;
        var factory = x.GetRequiredService<IUrlHelperFactory>();
        return factory.GetUrlHelper(actionContext);
    });
    

    IActionContextAccessorIUrlHelperFactory 都存在于 Microsoft.AspNetCore.Mvc.Core 包中。

    如果您使用的是 Microsoft.AspNetCore.All 元包,您应该已经引用了它。

    这应该可以帮助您解决问题。

    【讨论】:

    • 是的,问题中的那个 sn-p 来自同一个帖子并且没有工作。你有一个正在运行的例子吗?
    • 您希望新实例在哪里可用?内部控制器?或在视图中?还是在其他服务中?
    • 我在任何将调用 Url 助手的地方都需要这个。我希望在控制器、视图以及您可以使用这些帮助程序的其他任何地方都有一致的行为
    • .NetCore 框架,如果你看到的话,来自 controllerBase 类的 iUrlHelper 没有被注入。它是一种财产。当我们创建新的控制器时,如果我们显式注入 IUrlHelper,那么自定义 url 助手就会被正确注入(即上面的代码有效)。
    • 您是否尝试使用扩展方法代替?这可能更容易。
    【解决方案3】:

    你能不能通过像这样的字符串连接在你的解决方案中强行增加一些灵活性:

    public string SlugUrl(string slug, string url, bool tilde = false)
    {
        if (tilde) then
        {
            return Url.Content("~" + slug + url);
        }
        else
        {
            return Url.Content(slug + url);
        }
    }
    

    [...]

    string slug1 = "www.mysite.com";
    string slug2 = "www.mysite.com/Slug";
    string trailUrl = "/scripts/site.js";
    string result1 = SomeClass.SlugUrl(slug1, trailUrl);
    string result2 = SomeClass.SlugUrl(slug2, trailUrl);
    string result3 = SomeClass.SlugUrl(slug1, trailUrl, true);
    string result4 = SomeClass.SlugUrl(slug2, trailUrl, true);
    

    等等……

    【讨论】:

      猜你喜欢
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      相关资源
      最近更新 更多