如何将 slug 添加到 asp.net 核心网站的所有 Link 代?
How to add the slug to all Link generation in an asp.net core website?
我需要能够控制由我的 Url.Content("~")
调用生成的 link,以便能够在 link 的开头接受 Slug。基本上托管 URL 将位于负载均衡器之后,可能位于根级别或更友好的 Url...
举个例子:
站点在http://localhost:5001下配置为运行,所以Url.Content("~/scripts/site.js")
会生成"/scripts/site.js"
如果浏览器直接访问 url 甚至 www.mysite.com 这样的别名,这很好。
但我希望能够灵活地在 www.mysite.com/Slug 下托管网站(考虑证书等)...
现在我生成的 link 转到 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
的实例。
有没有一种方法可以在不创建自定义助手的情况下更改它(因为在某些区域会遗漏它并且会使调试几乎不可能找到误用的助手)
默认情况下,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);
});
IActionContextAccessor
和 IUrlHelperFactory
都在 Microsoft.AspNetCore.Mvc.Core
包中。
如果您使用的是 Microsoft.AspNetCore.All
元数据包,您应该已经引用了它。
这应该可以帮助您解决问题。
你能不能像这样通过字符串连接来暴力破解你的解决方案:
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);
等...
直接绑定 IUrlHelper
没有效果,因为 MVC 使用工厂在内部解析实例。要在您的控制器和 razor 视图中获取您自己的自定义 URL 帮助程序的实例,您需要在您的启动 class 中提供 IUrlHelperFactory
的自定义实现。
以下代码片段可让您用自己的功能修饰原始 URL 帮助程序:
在您的 Startup
class 中,您需要为 IUrlHelperFactory
添加具有单例范围 after 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);
}
}
我需要能够控制由我的 Url.Content("~")
调用生成的 link,以便能够在 link 的开头接受 Slug。基本上托管 URL 将位于负载均衡器之后,可能位于根级别或更友好的 Url...
举个例子:
站点在http://localhost:5001下配置为运行,所以Url.Content("~/scripts/site.js")
会生成"/scripts/site.js"
如果浏览器直接访问 url 甚至 www.mysite.com 这样的别名,这很好。
但我希望能够灵活地在 www.mysite.com/Slug 下托管网站(考虑证书等)...
现在我生成的 link 转到 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
的实例。
有没有一种方法可以在不创建自定义助手的情况下更改它(因为在某些区域会遗漏它并且会使调试几乎不可能找到误用的助手)
默认情况下,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);
});
IActionContextAccessor
和 IUrlHelperFactory
都在 Microsoft.AspNetCore.Mvc.Core
包中。
如果您使用的是 Microsoft.AspNetCore.All
元数据包,您应该已经引用了它。
这应该可以帮助您解决问题。
你能不能像这样通过字符串连接来暴力破解你的解决方案:
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);
等...
直接绑定 IUrlHelper
没有效果,因为 MVC 使用工厂在内部解析实例。要在您的控制器和 razor 视图中获取您自己的自定义 URL 帮助程序的实例,您需要在您的启动 class 中提供 IUrlHelperFactory
的自定义实现。
以下代码片段可让您用自己的功能修饰原始 URL 帮助程序:
在您的 Startup
class 中,您需要为 IUrlHelperFactory
添加具有单例范围 after 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);
}
}