Как добавить слаг ко всем ссылкам на основной сайт asp.net?
Мне нужно иметь возможность контролировать ссылки, генерируемые моим 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
, но я не могу ввести их и перезаписать текущие.
Я пробовал:
services.AddScoped<IUrlHelper>(x =>
{
var actionContext = x.GetService<IActionContextAccessor>().ActionContext;
return new MyCustomUrlHelper(actionContext);
});
но не смог сделать это. Когда я попытался отладить, я заметил, что если вы вызываете ту же команду в контроллере, вы получаете экземпляр Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper
вместо.
Есть ли способ изменить это без создания пользовательского помощника (потому что в некоторых областях это будет отсутствовать и отладка почти не сможет найти неправильно используемого помощника)
3 ответа
Переплет IUrlHelper
напрямую не имеет никакого эффекта, поскольку MVC внутренне разрешает экземпляр, используя фабрику. Чтобы получить экземпляр собственного настраиваемого помощника по URL в ваших контроллерах и представлениях бритвы, вам необходимо предоставить настраиваемую реализацию IUrlHelperFactory
в вашем классе запуска.
Следующие фрагменты кода позволяют вам украсить исходный 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);
}
}
IUrlHelper не является инъекционным по умолчанию.
Вам придется немного изменить свой код startup.cs, как описано в этом блоге.
Вы должны будете сначала зарегистрировать 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
metapackage вы уже должны ссылаться на это.
Это должно помочь вам решить вашу проблему.
Можете ли вы не просто использовать некоторую гибкость в своем решении с помощью конкатенации строк, например:
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);
так далее...