2013-04-15 13 views
59

Zasadniczo mam backend CMS, który zbudowałem przy użyciu ASP.NET MVC, a teraz przechodzę do strony frontend i muszę mieć możliwość ładowania stron z mojej bazy danych cms, na podstawie wprowadzonej trasy.Dynamic Routes z bazy danych dla ASP.NET MVC CMS

Jeśli użytkownik wejdzie na domain.com/students/information, MVC zajrzy do tabeli stron, aby sprawdzić, czy istnieje strona z łączem bezpośrednim, która pasuje do uczniów/informacji, jeśli tak, to przekieruje do kontrolera strony i następnie załaduj dane strony z bazy danych i zwróć je do widoku do wyświetlenia.

Do tej pory próbowałem złapać całą trasę, ale działa tylko dla dwóch segmentów adresu URL, więc/studenci/informacje, ale nie/studenci/informacje/upadek. Nie mogę znaleźć niczego online na temat tego, jak to osiągnąć, więc chciałem zapytać tutaj, zanim znajdę i otworzą źródłowe ASP.NET MVC cms i przeanalizuję kod.

Oto konfiguracja trasy, którą dotychczas miałem, ale uważam, że jest lepszy sposób na zrobienie tego.

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" } 
     );   
    } 

Jeśli ktoś może wskazać mi w dobrym kierunku, w jaki sposób byłoby przejść o ładowanie stron CMS z bazy danych, aż do trzech segmentów URL, i nadal będą mogli załadować stron podstawowych, które mają kontroler i wstępnie zdefiniowana akcja.

Odpowiedz

106

Możesz użyć ograniczenia, aby zdecydować, czy zastąpić domyślną logikę routingu.

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; 
    } 
} 

używać go w definicji trasy jak,

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 } 
); 

Teraz, jeśli masz akcję 'Index' kontroler 'PAGE' jak,

public ActionResult Index(string permalink) 
{ 
    //load the content from db with permalink 
    //show the content with view 
} 
  1. wszystkie adresy URL zostaną przechwycony przez pierwszą trasę i zweryfikowany przez ograniczenie.
  2. jeśli link bezpośredni istnieje w db, adres URL będzie obsługiwany przez działanie Index w kontrolerach stron.
  3. jeśli nie, ograniczenie się nie powiedzie, a adres URL powróci do domyślnej trasy (nie wiem, czy masz w projekcie jakieś inne kontrolery i jak zdecydujesz się na logikę 404).

EDIT

Aby uniknąć ponownego zapytań stronę CMS działania Index w Page kontrolera, można korzystać ze słownika HttpContext.Items, jak

w ograniczeniu

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; 

następnie w akcji,

public ActionResult Index(string permalink) 
{ 
    var page = HttpContext.Items["cmspage"] as CMSPage; 
    //show the content with view 
} 

mam nadzieję, że to pomoże.

+0

Dziękuję bardzo, spróbuję tego i oznaczę jako odpowiedź, jeśli zadziała. :) –

+3

Awesome działało świetnie, po prostu musiałem dodać czek, jeśli (wartości [parameterName]! = Null), ale poza tym idealnie! Dziękuję :) –

+1

serdecznie zapraszamy. Cieszę się, że to się udało. :) – shakib

Powiązane problemy