public Task Invoke(HttpContext context, IAbstractItemStorageProvider provider) { CancellationToken cancellationToken = context?.RequestAborted ?? CancellationToken.None; AbstractItemStorage abstractItems = provider.Get(); if (cancellationToken.IsCancellationRequested) { return(Task.CompletedTask); } var startPage = abstractItems .GetStartPage(context.Request.Host.Value, _filterAccessor?.Get()); if (startPage is null) { throw new StartPageNotFoundException(context.Request.Host.Value); } context.Items[RoutingKeys.StartPage] = startPage; context.Items[RoutingKeys.AbstractItemStorage] = abstractItems; // Call the next delegate/middleware in the pipeline return(_next(context)); }
public override Task RouteAsync(RouteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var startPage = context.HttpContext.Items[RoutingKeys.StartPage] as IStartPage;//стартовая страница, проставляется в RoutingMiddleware if (startPage == null) { return(Task.CompletedTask); } var targetingFilter = TargetingProvider?.Get();//все зарегистрированные фильтры структуры сайта, объединенные в один //вычислим PathData текущего запроса - какая страница в структуре сайта должна быть активирована PathData data = null; if (SavePathDataInHttpContext) { //может быть в рамках текущего запроса мы уже вычислили PathData и сохранили его в HttpContext //тогда получим его оттуда и не будем повторно вычислять data = context.HttpContext.Items[RoutingKeys.PathData] as PathData; } if (data == null) { //особый кейс: хотим открыть страницу сайта по её id, например, из админки структуры сайта //в этом случае мы находимся в режиме onScreen и передан id страницы (abstractItem'а) var onScreenContext = context.HttpContext.Items[OnScreenModeKeys.OnScreenContext] as OnScreenContext; var abstractItemStorage = context.HttpContext.Items[RoutingKeys.AbstractItemStorage] as AbstractItemStorage; if (onScreenContext?.Enabled == true && onScreenContext?.PageId.HasValue == true && abstractItemStorage != null) { var abstractItem = abstractItemStorage.Get(onScreenContext.PageId.Value); var isContainInStartPage = IsStartPageContainAbstractItem(startPage, abstractItem); if (isContainInStartPage) { data = new PathData(abstractItem, ""); } } } var path = context.HttpContext.Request.Path; if (data == null) { //вычислим PathData разбирая урл запроса, и сопоставляя сегменты со структурой сайта data = CreatePathFinder().Find(path, startPage, targetingFilter, HeadUrlResolver); } if (data == null) { return(Task.CompletedTask); } if (SavePathDataInHttpContext) { context.HttpContext.Items[RoutingKeys.PathData] = data; } var controllerName = ControllerMapper.Map(data.AbstractItem); if (string.IsNullOrEmpty(controllerName)) { return(Task.CompletedTask); } //проставим AbstractItem в RouteData context.RouteData.Values[RoutingKeys.CurrentItem] = data.AbstractItem.Id; context.RouteData.DataTokens[RoutingKeys.CurrentItem] = data.AbstractItem; //подменим HttpContext.Request.Path, т.к. он используется в RouteBase при матчинге с шаблоном роута context.HttpContext.Items["original-path"] = context.HttpContext.Request.Path; context.HttpContext.Request.Path = $"/{controllerName}{data.RemainingUrl}"; //альтернативно можно вместо использования механизма c матчингом шаблона из RouteBase //самому наполнить context.RouteData.Values, но тогда при регистрации роутов придётся отказаться от "{controller}/{action=Index}/{id?}" return(base.RouteAsync(context)); }