Перечисление возможностей, разрешенных грамматикой:
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
Конечно, если (high-low)%stride != 0
, то конечная точка будет немного ниже high-1
.
Если stride
отрицательно, порядок изменяется немного, так как мы отсчитываем:
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
Расширенные нарезки (с запятыми и эллипсами) в основном используются только специальными структурами данных (например, Numpy) ; основные последовательности не поддерживают их.
>>> class slicee:
... def __getitem__(self, item):
... return `item`
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
Вы можете сделать это, создав новый маршрут и добавив его в коллекцию маршрутов в RegisterRoutes в своем global.asax. Ниже приведен очень простой пример пользовательского маршрута:
public class ExampleRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var url = httpContext.Request.Headers["HOST"];
var index = url.IndexOf(".");
if (index < 0)
return null;
var subDomain = url.Substring(0, index);
if (subDomain == "user1")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User1"); //Goes to the User1Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User1Controller
return routeData;
}
if (subDomain == "user2")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User2"); //Goes to the User2Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User2Controller
return routeData;
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//Implement your formating Url formating here
return null;
}
}
После определения нового обработчика маршрута, который будет смотреть на хост, переданный в URL , вы можете пойти с идеей базового контроллера, который знает о том, к какому узлу он обращается. Это выглядит так:
public abstract class SiteController : Controller {
ISiteProvider _siteProvider;
public SiteController() {
_siteProvider = new SiteProvider();
}
public SiteController(ISiteProvider siteProvider) {
_siteProvider = siteProvider;
}
protected override void Initialize(RequestContext requestContext) {
string[] host = requestContext.HttpContext.Request.Headers["Host"].Split(':');
_siteProvider.Initialise(host[0]);
base.Initialize(requestContext);
}
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
ViewData["Site"] = Site;
base.OnActionExecuting(filterContext);
}
public Site Site {
get {
return _siteProvider.GetCurrentSite();
}
}
}
ISiteProvider
- простой интерфейс:
public interface ISiteProvider {
void Initialise(string host);
Site GetCurrentSite();
}
Я отсылаю вас к Luke Sampson Blog
Чтобы захватить субдомен при использовании веб-API, переопределите селектор действий, чтобы ввести параметр запроса subdomain
. Затем используйте параметры запроса поддомена в действиях ваших контроллеров следующим образом:
public string Get(string id, string subdomain)
Этот подход делает отладку удобной, поскольку вы можете указать параметр запроса вручную при использовании localhost вместо фактическое имя хоста (подробности см. в стандартном ответе маршрутизации MVC5 ). Это код для Action Selector:
class SubdomainActionSelector : IHttpActionSelector
{
private readonly IHttpActionSelector defaultSelector;
public SubdomainActionSelector(IHttpActionSelector defaultSelector)
{
this.defaultSelector = defaultSelector;
}
public ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor)
{
return defaultSelector.GetActionMapping(controllerDescriptor);
}
public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var routeValues = controllerContext.Request.GetRouteData().Values;
if (!routeValues.ContainsKey("subdomain")) {
string host = controllerContext.Request.Headers.Host;
int index = host.IndexOf('.');
if (index >= 0)
controllerContext.Request.GetRouteData().Values.Add("subdomain", host.Substring(0, index));
}
return defaultSelector.SelectAction(controllerContext);
}
}
Замените селектор действий по умолчанию, добавив его в WebApiConfig.Register
:
config.Services.Replace(typeof(IHttpActionSelector), new SubdomainActionSelector(config.Services.GetActionSelector()));
Если вы ищете возможности MultiTenancy для вашего проекта с разными доменами / поддоменами для каждого арендатора, вы должны посмотреть на SaasKit:
https://github.com/saaskit / saaskit
Примеры кода можно увидеть здесь: http://benfoster.io/blog/saaskit-multi-tenancy-made-easy
Некоторые примеры с использованием ядра ASP.NET: http://andrewlock.net/forking-the-pipeline-adding-tenant-specific-files-with-saaskit-in-asp-net-core/
EDIT: Если вы не хотите использовать SaasKit в своем основном проекте ASP.NET, вы можете взглянуть на реализацию Мартинской маршрутизации домена для MVC6: https: //blog.maartenballiauw
Однако эти Gists не поддерживаются и должны быть настроены для работы с последней версией ядра ASP.NET.
Прямая ссылка на код: https://gist.github.com/maartenba/77ca6f9cfef50efa96ec# файл-domaintemplaterout ebuilderextensions-CS
В ядре ASP.NET хост доступен через Request.Host.Host
. Если вы хотите разрешить переопределение хоста через параметр запроса, сначала проверьте Request.Query
.
Чтобы заставить параметр запроса узла распространяться на новые URL-адреса на основе маршрутов, добавьте этот код в app.UseMvc
конфигурация маршрута:
routes.Routes.Add(new HostPropagationRouter(routes.DefaultHandler));
И определите HostPropagationRouter
следующим образом:
/// <summary>
/// A router that propagates the request's "host" query parameter to the response.
/// </summary>
class HostPropagationRouter : IRouter
{
readonly IRouter router;
public HostPropagationRouter(IRouter router)
{
this.router = router;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
if (context.HttpContext.Request.Query.TryGetValue("host", out var host))
context.Values["host"] = host;
return router.GetVirtualPath(context);
}
public Task RouteAsync(RouteContext context) => router.RouteAsync(context);
}
Это не моя работа, но я должен был добавить ее в этот ответ.
Вот отличное решение этой проблемы. Maartin Balliauw написал код, который создает класс DomainRoute, который можно использовать очень похоже на обычную маршрутизацию.
http://blog.maartenballiauw.be/post/2009/05/20/ASPNET- MVC-Domain-Routing.aspx
Пример использования будет таким:
routes.Add("DomainRoute", new DomainRoute(
"{customer}.example.com", // Domain with parameters
"{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
))
;
Я создал библиотеку для маршрутизации поддоменов , которую вы можете создать таким маршрутом. Он работает в настоящее время для .NET Core 1.1 и .NET Framework 4.6.1, но будет обновлен в ближайшем будущем. Вот как это работает: 1) Маршрут субдомена карты в Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var hostnames = new[] { "localhost:54575" };
app.UseMvc(routes =>
{
routes.MapSubdomainRoute(
hostnames,
"SubdomainRoute",
"{username}",
"{controller}/{action}",
new { controller = "Home", action = "Index" });
)};
2) Контроллеры / HomeController.cs
public IActionResult Index(string username)
{
//code
}
3) Это lib также позволит вы создаете URL-адреса и формы. Код:
@Html.ActionLink("User home", "Index", "Home" new { username = "user1" }, null)
Сгенерирует <a href="http://user1.localhost:54575/Home/Index">User home</a>
Сгенерированный URL-адрес также будет зависеть от текущего местоположения хоста и схемы. Вы также можете использовать html-помощники для BeginForm
и UrlHelper
. Если вам нравится, вы также можете использовать новую функцию, называемую помощниками тегов (FormTagHelper
, AnchorTagHelper
). У lib еще нет документации, но есть некоторые тесты и примеры проектов, поэтому не стесняйтесь исследовать их.
Да, но вы должны создать свой собственный обработчик маршрута.
Как правило, маршрут не знает о домене, потому что приложение может быть развернуто в любом домене, и маршрут не будет волновать так или иначе. Но в вашем случае вы хотите установить контроллер и действие из домена, поэтому вам нужно будет создать настраиваемый маршрут, который будет знать о домене.