ASP.NET MVC CMS数据库的动态路由如何实现?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (23)

基本上我有一个使用ASP.NET MVC构建的CMS后端,现在我正在转到前端网站,并且需要能够根据输入的路由从我的cms数据库加载页面。

因此,如果用户输入domain.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'控制器中有'索引'操作,

public ActionResult Index(string permalink)
{
    //load the content from db with permalink
    //show the content with view
}
  1. 所有的网址都会被第一条路线拦截并通过约束条件进行验证。
  2. 如果永久链接存在于数据库中,则URL将由页面控制器中的索引动作处理。
  3. 如果不是,约束将失败,url将回退到默认路由(我不知道你是否有任何其他控制器在项目中,以及如何决定你的404逻辑)。

为了避免IndexPage控制器的操作中重新查询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
}

扫码关注云+社区