Динамические маршруты из базы данных для ASP.NET MVC CMS
в основном у меня есть бэкэнд CMS, который я построил с помощью ASP.NET MVC и теперь я перехожу на сайт frontend и должен иметь возможность загружать страницы из моей базы данных cms, основываясь на введенном маршруте.
Так что если пользователь вводит domain.com/students/information, MVC будет искать в таблице pages, чтобы увидеть, существует ли страница с постоянной ссылкой, которая соответствует students/information, если это так, она перенаправит на контроллер страницы, а затем загрузит данные страницы из базы данных и вернет их в базу данных. просмотр для отображения.
до сих пор я пытался поймать весь маршрут, но он работает только для двух сегментов URL, поэтому /students/information, но не /students/information/fall. Я не могу найти ничего в интернете о том, как это сделать, поэтому я бы спросил здесь, прежде чем найти и открыть исходный код ASP.NET MVC cms и рассекает код.
вот конфигурация маршрута у меня есть до сих пор, но я чувствую, что есть лучший способ сделать это.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Default route to handle core pages
routes.MapRoute(null,"{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new { controller = "Index" }
);
// CMS route to handle routing to the PageController to check the database for the route.
var db = new MvcCMS.Models.MvcCMSContext();
//var page = db.CMSPages.Where(p => p.Permalink == )
routes.MapRoute(
null,
"{*.}",
new { controller = "Page", action = "Index" }
);
}
Если кто-нибудь может мне точку в правильном направлении о том, как я буду загружать страницы CMS из базы данных, до трех сегментов URL, и по-прежнему иметь возможность загружать основные страницы, которые имеют предопределенный контроллер и действие.
1 ответ:
вы можете использовать ограничение, чтобы решить, следует ли переопределить логику маршрутизации по умолчанию.
public class CmsUrlConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { var db = new MvcCMS.Models.MvcCMSContext(); if (values[parameterName] != null) { var permalink = values[parameterName].ToString(); return db.CMSPages.Any(p => p.Permalink == permalink); } return false; } }
используйте его в определении маршрута, например,
routes.MapRoute( name: "CmsRoute", url: "{*permalink}", defaults: new {controller = "Page", action = "Index"}, constraints: new { permalink = new CmsUrlConstraint() } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
теперь, если у вас есть действие "индекс" в контроллере "страница", например,
public ActionResult Index(string permalink) { //load the content from db with permalink //show the content with view }
- все URL-адреса будут пойманы первым маршрутом и будут проверены ограничением.
- если Постоянная ссылка существует в БД, url-адрес будет обрабатываться действием индекса в контроллере страницы.
- если не ограничение не будет выполнено, и url-адрес вернется к маршруту по умолчанию (я не знаю, есть ли у вас другие контроллеры в проекте и как вы решите свою логику 404).
EDIT
чтобы избежать повторного запроса страницы cms в
Index
действий можно использоватьHttpContext.Items
словарь, какограничения
var db = new MvcCMS.Models.MvcCMSContext(); if (values[parameterName] != null) { var permalink = values[parameterName].ToString(); var page = db.CMSPages.Where(p => p.Permalink == permalink).FirstOrDefault(); if(page != null) { HttpContext.Items["cmspage"] = page; return true; } return false; } return false;
тогда в действии,
public ActionResult Index(string permalink) { var page = HttpContext.Items["cmspage"] as CMSPage; //show the content with view }
надеюсь, что это помогает.