public IActionResult RequestHandler(PageControllerModel model) { Page page = HttpContext.Items["RequestedPage"] as Page; switch (page) { case UsualPage up: try { SetVisitorInfo(up.ID, PagesManagement.PageType.Usual); } catch { } return(UsualPage(up)); case CategoryPage cp: try { SetVisitorInfo(cp.ID, PagesManagement.PageType.Category); } catch { } return(CategoryPage(cp, model)); case ProductPage pp: try { SetVisitorInfo(pp.ID, PagesManagement.PageType.Product); } catch { } return(ProductPage(pp)); default: return(Redirect(HttpContext.Items["Redirection"] as string)); } }
public IActionResult CategoryPage(CategoryPage categoryPage, PageControllerModel model) { Template template = db.Templates.AsNoTracking().FirstOrDefault(t => t.ID == categoryPage.TemplateId); if (template != null) { ConfigurationHandler config = HttpContext.RequestServices.GetService <ConfigurationHandler>(); // Получаем список продуктов IQueryable <ProductPage> categoryProducts = db.ProductPages.Where(pp => pp.Published && pp.PreviousPageID == categoryPage.ID); categoryPage.ProductsCount = (uint)categoryProducts.Count(); // Без OrderBy(pp => pp.ID) Mysql на Windows игнорирует сортировку по ID по умолчанию categoryProducts = categoryProducts.OrderBy(pp => pp.ID); // Производим сортировку, если задано значение if (model.Orderby.HasValue) { switch (model.Orderby) { case OrderBy.ascending_price: categoryProducts = categoryProducts.OrderBy(pp => pp.Price); break; case OrderBy.descending_price: categoryProducts = categoryProducts.OrderByDescending(pp => pp.Price); break; } } // Получаем количество товаров на странице int?maxProductOnPage = null; try { maxProductOnPage = Convert.ToInt32(config.GetConfigValue("CategoryPageSettings:NumberOfProductsOnPage")); } catch (FormatException) { } // Если значение верное, то отбираем заданное количество товаров if (maxProductOnPage.HasValue && maxProductOnPage.Value >= 1) { int pagesCount = GetPagesCount((int)categoryPage.ProductsCount, maxProductOnPage.Value); HttpContext.Items["PagesCount"] = pagesCount; HttpContext.Items["PaginationStyleName"] = config.GetConfigValue("CategoryPageSettings:PaginationStyleName"); //Если задана страница, то скипаем предыдущие товары для дальнейшего отбора if (model.Page.HasValue && model.Page.Value > 1 && model.Page.Value <= pagesCount) { HttpContext.Items["CurrentPage"] = model.Page.Value; categoryProducts = categoryProducts.Skip((model.Page.Value - 1) * maxProductOnPage.Value); } if (HttpContext.Items["CurrentPage"] == null) { HttpContext.Items["CurrentPage"] = 1; } categoryProducts = categoryProducts.Take(maxProductOnPage.Value); } else { HttpContext.Items["CurrentPage"] = 1; HttpContext.Items["PagesCount"] = 1; } List <ProductPage> products = categoryProducts.AsNoTracking().ToList(); HttpContext.Items["products"] = products; return(View(template.TemplatePath, categoryPage)); } return(Content(categoryPage.Content)); }
public IActionResult SearchPage(PageControllerModel model) { ConfigurationHandler config = HttpContext.RequestServices.GetRequiredService <ConfigurationHandler>(); Template template = null; try { int pageNotFoundTemplateId = Convert.ToInt32(config.GetConfigValue("SearchPageSettings:SearchPageTemplateId")); template = db.Templates.AsNoTracking().FirstOrDefault(t => t.ID == pageNotFoundTemplateId); if (template == null) { throw new FormatException(); } } catch (FormatException) { return(PageNotFound()); } int maxSymbols = 0; try { maxSymbols = Convert.ToInt32(config.GetConfigValue("SearchPageSettings:MaxNumberOfSymbolsInSearchQuery")); } catch (FormatException) { maxSymbols = 0; } if (!string.IsNullOrEmpty(model.Search)) { if (model.Search.Length > maxSymbols) { model.Search = model.Search.Substring(0, maxSymbols); } LinkedList <string> searchQueryList = new LinkedList <string>(); searchQueryList.AddLast(model.Search); // Получаем все выражения и синонимы, которые встретились в поисковом запросе. Создаем для каждого выражения и синонима регулярное выражение var synonymsForStringsWithRegex = db.SynonymsForStrings.Where(s => model.Search.Contains(s.String, StringComparison.InvariantCultureIgnoreCase) || model.Search.Contains(s.Synonym, StringComparison.InvariantCultureIgnoreCase)).AsNoTracking() .Select(s => new { s.String, s.Synonym, StringRegex = new Regex($"(?(^{s.String})" + $"(?(^{s.String}$)(^{s.String}$)|(^{s.String} ))" + // если проверяемое выражение начинается и заканчивается со String или, если начинает, но не заканчивается на String $"|(?( {s.String}$)( {s.String}$)|( {s.String} ))" + // если проверяемое выражение не начинается со String, но заканчивается на нем или, если не начинает и не заканчивается на String ")", RegexOptions.IgnoreCase ), SynonymRegex = new Regex($"(?(^{s.Synonym})" + // так же, как и сверху, только для Synonym $"(?(^{s.Synonym}$)(^{s.Synonym}$)|(^{s.Synonym} ))" + $"|(?( {s.Synonym}$)( {s.Synonym}$)|( {s.Synonym} ))" + ")", RegexOptions.IgnoreCase ) }).ToArray(); // На основе всех совпадений из таблицы SynonymsForStrings создаем все возможные вариации текущего запроса foreach (var synonymForStringWithRegex in synonymsForStringsWithRegex) { for (var it = searchQueryList.First; it != null; it = it?.Next) { if (synonymForStringWithRegex.StringRegex.IsMatch(it.Value)) { searchQueryList.AddFirst(it.Value.Replace(synonymForStringWithRegex.String, synonymForStringWithRegex.Synonym, StringComparison.InvariantCultureIgnoreCase)); } else if (synonymForStringWithRegex.SynonymRegex.IsMatch(it.Value)) { searchQueryList.AddFirst(it.Value.Replace(synonymForStringWithRegex.Synonym, synonymForStringWithRegex.String, StringComparison.InvariantCultureIgnoreCase)); } } } // Создаем запрос к бд для каждого поиского запроса LinkedList <IQueryable <ProductPage> > queries = new LinkedList <IQueryable <ProductPage> >(); foreach (var searchQuery in searchQueryList) { string[] subSearchQuery = searchQuery.Split(' ', StringSplitOptions.RemoveEmptyEntries); IQueryable <ProductPage> query = null; foreach (var s in subSearchQuery) { if (query == null) { query = db.ProductPages.Where(pp => pp.Published && pp.PageName.Contains(s, StringComparison.InvariantCultureIgnoreCase)); } else { query = query.Where(pp => pp.Published && pp.PageName.Contains(s, StringComparison.InvariantCultureIgnoreCase)); } } if (query != null) { queries.AddLast(query); } } if (queries.Count > 0) { // Объединяем полученные запросы к бд через Union, чтобы избежать дубликатов IQueryable <ProductPage> finalQuery = queries.First.Value; for (var it = queries.First.Next; it != null; it = it.Next) { finalQuery = finalQuery.Union(it.Value).OrderBy(pp => pp.ID); } // Получаем количество товаров на странице int?maxProductOnPage = null; try { maxProductOnPage = Convert.ToInt32(config.GetConfigValue("CategoryPageSettings:NumberOfProductsOnPage")); } catch (FormatException) { } // Если значение верное, то отбираем заданное количество товаров if (maxProductOnPage.HasValue && maxProductOnPage.Value >= 1) { int pagesCount = GetPagesCount(finalQuery.Count(), maxProductOnPage.Value); HttpContext.Items["PagesCount"] = pagesCount; HttpContext.Items["PaginationStyleName"] = config.GetConfigValue("CategoryPageSettings:PaginationStyleName"); HttpContext.Items["OrderBy"] = model.Orderby; //Если задана страница, то скипаем предыдущие товары для дальнейшего отбора if (model.Page.HasValue && model.Page.Value > 1 && model.Page.Value <= pagesCount) { HttpContext.Items["CurrentPage"] = model.Page.Value; finalQuery = finalQuery.Skip((model.Page.Value - 1) * maxProductOnPage.Value); } if (HttpContext.Items["CurrentPage"] == null) { HttpContext.Items["CurrentPage"] = 1; } finalQuery = finalQuery.Take(maxProductOnPage.Value); } else { HttpContext.Items["CurrentPage"] = 1; HttpContext.Items["PagesCount"] = 1; } // Получаем список найденных товаров HttpContext.Items["products"] = finalQuery.AsNoTracking().ToList(); } } return(View(template.TemplatePath)); }