简体   繁体   English

如何将slug添加到asp.net核心网站中的所有Link生成?

[英]How to add the slug to all Link generation in an asp.net core website?

I need to be able to control the links being generated by my Url.Content("~") call to be able to accept a Slug in the beginning of the link. 我需要能够控制我的Url.Content("~")调用生成的链接,以便能够在链接的开头接受Slug。 Basically the hosting URL will be behind a Load-balancer and may be at the root level or behind a friendlier Url... 基本上托管URL将位于负载均衡器后面,可能位于根级别或更友好的URL后面...

As an example: The site is configured to run under http://localhost:5001 , so Url.Content("~/scripts/site.js") will generate "/scripts/site.js" 例如:该站点配置为在http:// localhost:5001下运行,因此Url.Content("~/scripts/site.js")将生成"/scripts/site.js"

this is fine if the browser is coming directly to that url or even to an alias such as www.mysite.com. 如果浏览器直接访问该URL或甚至是别名(如www.mysite.com),这都没问题。

But i want o be able to have the flexibility to host the site under www.mysite.com/Slug (think certs and such)... 但我希望o能够灵活地在www.mysite.com/Slug下托管该网站(想想证书等)......

now my link that was generated goes to www.mysite.com/scripts.site.js which resolves to a 404. 现在我生成的链接转到www.mysite.com/scripts.site.js,它解析为404。

Ideally, the slug can be configured in a custom IUrlHelper , or even a custom LinkGenerator , but i cannot seem to inject those and overwrite the current ones. 理想情况下,蛞蝓可以在自定义配置IUrlHelper ,甚至是自定义的LinkGenerator ,但我似乎无法注入那些和覆盖当前的。

I've tried: 我试过了:

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

but was unable to get that injected. 但无法注入。 When i tried debugging, I noticed that if you call the same command in a controller, you get an instance of Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper instead. 当我尝试调试时,我注意到如果在控制器中调用相同的命令,则会获得Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper的实例。

Is there a way to change that without creating a custom helper (because that will be missed in some areas and will make debugging near impossible to find the misused helper) 有没有办法在不创建自定义帮助程序的情况下更改它(因为在某些区域会丢失并且几乎不可能找到被滥用的帮助程序)

Binding IUrlHelper directly has no effect, as MVC internally resolves the instance using a factory. 直接绑定IUrlHelper无效,因为MVC在内部使用工厂解析实例。 To get an instance of your own custom URL helper in your controllers and razor views, you need to provide a custom implementation of IUrlHelperFactory in your startup class. 要在控制器和剃刀视图中获取自己的自定义URL帮助程序的实例,您需要在启动类中提供IUrlHelperFactory的自定义实现。

The following code snippets allow you to decorate the original URL helper with your own functionality: 以下代码段允许您使用自己的功能装饰原始URL帮助程序:

In your Startup class, you need to add the custom implementation for IUrlHelperFactory with singleton scope after AddMvc : Startup类中,您需要 AddMvc 之后IUrlHelperFactory添加自定义实现和单例范围:

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

And the custom implementation could look like this: 自定义实现可能如下所示:

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

The IUrlHelper is not injectable by default. IUrlHelper默认不可注入。

You will have to modify your startup.cs code a bit as explained in this blog. 您将不得不修改您的startup.cs代码,如本博客中所述。

You will have to first register IActionContextAccessor. 您必须先注册IActionContextAccessor。

Then with the help of UrlHelperFactory, you can inject your custom implementation as shown below: 然后在UrlHelperFactory的帮助下,您可以注入自定义实现,如下所示:

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

Both IActionContextAccessor and IUrlHelperFactory live in the Microsoft.AspNetCore.Mvc.Core package. IActionContextAccessorIUrlHelperFactory存在于Microsoft.AspNetCore.Mvc.Core包中。

If you're using the Microsoft.AspNetCore.All metapackage you should have this referenced already. 如果您正在使用Microsoft.AspNetCore.All元数据包,那么您应该已经引用了它。

This should help you to resolve your problem. 这应该可以帮助您解决问题。

Can you not just brute force some flexibility into your solution with string concatenation like this: 您是否可以通过字符串连接强制一些灵活性进入您的解决方案,如下所示:

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

etc... 等等...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM