c# - framework - Rutas dinámicas desde la base de datos para ASP.NET MVC CMS
web forms c# ejemplos (1)
Básicamente, tengo un back-end CMS que construí usando ASP.NET MVC y ahora me estoy moviendo al sitio frontend y necesito poder cargar páginas desde mi base de datos cms, de acuerdo con la ruta ingresada.
Entonces, si el usuario ingresa a domain.com/students/information, MVC miraría en la tabla de páginas para ver si existe una página que tenga un enlace permanente que coincida con estudiantes / información, de ser así redirigiría al controlador de página y luego cargaría la página datos de la base de datos y devolverlos a la vista para su visualización.
Hasta ahora he intentado tener una ruta de atrapar todo, pero solo funciona para dos segmentos de URL, entonces / students / information, pero no / students / information / fall. No puedo encontrar nada en línea sobre cómo lograr esto, así que pensé en preguntar aquí, antes de encontrar y abrir código ASP.NET MVC cms y analizar el código.
Esta es la configuración de ruta que tengo hasta ahora, pero creo que hay una mejor manera de hacerlo.
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" }
);
}
Si alguien puede orientarme en la dirección correcta sobre cómo cargar las páginas de CMS desde la base de datos, con hasta tres segmentos de URL, y aún así poder cargar páginas centrales, que tengan un controlador y una acción predefinidos.
Puede usar una restricción para decidir si se sobrescribe la lógica de enrutamiento predeterminada.
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;
}
}
úsalo en la definición de ruta como,
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 }
);
Ahora si tiene una acción ''Index'' en ''Page'' Controller como,
public ActionResult Index(string permalink)
{
//load the content from db with permalink
//show the content with view
}
- todas las URL serán atrapadas por la primera ruta y serán verificadas por la restricción.
- si el enlace permanente existe en db, la URL se manejará mediante acción de índice en el controlador de la página.
- de lo contrario, la restricción fallará y la url volverá a la ruta predeterminada (no sé si tiene otros controladores en el proyecto y cómo va a decidir su lógica 404).
EDITAR
Para evitar consultar la página cms en la acción Index
en el controlador de Page
, se puede usar el diccionario HttpContext.Items
, como
en la restricción
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;
luego en la acción,
public ActionResult Index(string permalink)
{
var page = HttpContext.Items["cmspage"] as CMSPage;
//show the content with view
}
espero que esto ayude.