Подтвердить что ты не робот

Динамические маршруты из базы данных для ASP.NET MVC CMS

В основном у меня есть сервер CMS, который я создал с помощью ASP.NET MVC, и теперь я перехожу к сайту frontend и должен иметь возможность загружать страницы из моей базы данных cms на основе введенного маршрута.

Таким образом, если пользователь вводит domain.com/students/information, MVC будет искать в таблице страниц, чтобы увидеть, существует ли страница, которая имеет постоянную ссылку, которая соответствует учащимся/информации, если это так будет перенаправлено на контроллер страницы, а затем загрузите данные страницы из базы данных и верните их в представление для отображения.

До сих пор я пытался поймать весь маршрут, но он работает только для двух сегментов URL, так что/студентов/информации, но не /students/information/fall. Я не могу найти что-либо в Интернете о том, как это сделать, поэтому, хотя я бы спросил здесь, прежде чем найти и скомпилировать ASP.NET MVC с открытым исходным кодом и проанализировать код.

Вот конфигурация маршрута, которая у меня есть до сих пор, но я считаю, что есть лучший способ сделать это.

 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-сегментов и все еще иметь возможность загружать основные страницы, которые имеют предопределенный контроллер и действие.

4b9b3361

Ответ 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 }
);

Теперь, если у вас есть действие "Index" в "Page" контроллере, например,

public ActionResult Index(string permalink)
{
    //load the content from db with permalink
    //show the content with view
}
  • все URL-адреса будут пойманы по первому маршруту и ​​будут проверены ограничением.
  • Если постоянная ссылка существует в db, то URL-адрес будет обрабатываться указателем в контроллере страницы.
  • Если не будет сдерживать ограничение, и url вернется к маршруту по умолчанию (я не знаю, есть ли у вас какие-либо другие контроллеры в проекте и как вы решите свою логику 404).

ИЗМЕНИТЬ

Чтобы избежать запроса страницы cms в Index в контроллере Page, можно использовать словарь 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
}

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

Ответ 2

Я использую более простой подход, который не требует никакой специальной обработки маршрутизатора. Просто создайте один/глобальный контроллер, который обрабатывает несколько необязательных параметров, затем обработайте эти параметры так, как вам нравится:

//Route all traffic through this controller with the base URL being the domain
[Route("")]
public class MyController : Controller
{
    //Define up to 5 optional  patrameters
    [HttpGet("{a1?}/{a2?}/{a3?}/{a4?}/{a5?}")]
    public async Task<JsonResult> APIGet(string a1 = "", string a2 = "", string a3 = "", string a4 = "", string a5 = "")
    {
        //Custom logic processing each of the route variables
        return Json(new string[] { a1, a2, a3, a4, a5 });
    }
}

Пример вывода на domain.com/test1/test2

["test1","test2","","",""]