动态路由从数据库为ASP.. Net MVC cms
本文关键字:Net MVC cms ASP 路由 数据库 动态 | 更新日期: 2023-09-27 18:09:34
基本上我有一个CMS后端我使用ASP构建。. NET MVC,现在我移动到前端网站,需要能够加载页面从我的CMS数据库,基于输入的路由。
因此,如果用户输入example.com/students/information
, MVC将在页面表中查看是否存在具有与学生/信息匹配的永久链接的页面,如果存在,它将重定向到页面控制器,然后从数据库加载页面数据并将其返回给视图显示。
到目前为止,我试图有一个捕获所有路由,但它只适用于两个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段,仍然能够加载核心页面,有一个预定义的控制器和动作。
您可以使用约束来决定是否覆盖默认路由逻辑。
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 }
);
现在如果你在'Page'控制器中有一个'Index'动作,比如
public ActionResult Index(string permalink)
{
//load the content from db with permalink
//show the content with view
}
- 所有的url将被第一个路由捕获,并通过约束进行验证。 如果永久链接在数据库中存在,url将被页控制器中的索引操作处理。
- 如果没有约束将失败,url将回退到默认路由(我不知道你是否在项目中有任何其他控制器以及你将如何决定你的404逻辑)。
编辑
为了避免在Page
控制器的Index
操作中重新查询cms页面,可以使用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
}
我使用更简单的方法,不需要任何自定义路由器处理。只需创建一个单独的/全局控制器来处理几个可选参数,然后按您喜欢的方式处理这些参数:
//Route all traffic through this controller with the base URL being the domain
[Route("")]
[ApiController]
public class ValuesController : ControllerBase
{
//GET api/values
[HttpGet("{a1?}/{a2?}/{a3?}/{a4?}/{a5?}")]
public ActionResult<IEnumerable<string>> Get(string a1 = "", string a2 = "", string a3 = "", string a4 = "", string a5 = "")
{
//Custom logic processing each of the route values
return new string[] { a1, a2, a3, a4, a5 };
}
}
example.com/test1/test2/test3
的样本输出
["test1","test2","test3","",""]