Динамические маршруты из базы данных для 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 61

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
}
  1. все URL-адреса будут пойманы первым маршрутом и будут проверены ограничением.
  2. если Постоянная ссылка существует в БД, url-адрес будет обрабатываться действием индекса в контроллере страницы.
  3. если не ограничение не будет выполнено, и 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
}

надеюсь, что это помогает.