动态路由从数据库为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段,仍然能够加载核心页面,有一个预定义的控制器和动作。

动态路由从数据库为ASP.. Net MVC cms

您可以使用约束来决定是否覆盖默认路由逻辑。

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
}
  1. 所有的url将被第一个路由捕获,并通过约束进行验证。
  2. 如果永久链接在数据库中存在,url将被页控制器中的索引操作处理。
  3. 如果没有约束将失败,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","",""]