我想将所有CMS页面网址映射到单个控制器(PageController)和操作(详细信息)。
如何创建自定义路由以映射所有这些网址?
/teacher
/teacher/kindergarten
/teacher/kindergarten/1
/teacher/primary
/teacher/primary/english
/teacher/primary/language
/teacher/primary/language/chinese
/teacher/primary/math
/teacher/primary/science
/parent
/parent/kindergarten
/parent/primary1-3
/parent/primary4-6
/leader
/leader/kindergarten
/leader/kindergarten/1
答案 0 :(得分:1)
如果您在数据库中有这些URL,则可以在应用程序启动时映射路由:
var pages = siteDB.Pages.ToList();
string pagePath = "";
foreach (var page in pages)
{
routeVals = new RouteValueDictionary();
constraints = new RouteValueDictionary();
routeVals.Add("controller", "page");
routeVals.Add("action", "details");
constraints.Add("path", "[a-zA-Z0-9\\-]*");
// any child pages? must add these routes before their parent pages.
var childPages = siteDB.Pages.Where(p => p.ParentPageId == page.PageId).ToList();
foreach (var childPage in childPages)
{
pagePath = BuildPath(childPage);
RouteTable.Routes.Add(new Route(pagePath, new MvcRouteHandler())
{
Defaults = routeVals,
Constraints = constraints,
DataTokens =
new RouteValueDictionary {
{ "pageid", childPage.PageId },
{ "path", pagePath }
}
});
// Any further child pages? (Only 3 levels supported)
var childSubPages = siteDB.Pages.Where(p => p.ParentPageId == childPage.PageId).ToList();
foreach (var childSubPage in childSubPages)
{
pagePath = BuildPath(childSubPage);
RouteTable.Routes.Add(new Route(pagePath, new MvcRouteHandler())
{
Defaults = routeVals,
Constraints = constraints,
DataTokens =
new RouteValueDictionary {
{ "pageid", childSubPage.PageId },
{ "path", pagePath }
}
});
}
}
此代码从数据库中获取页面,这些页面由父ID链接。
这是BuildPath函数,它生成每个页面的完整路径:
public static string BuildPath(Page page)
{
if (page.ParentPageId == 1)
{
return page.PageKey;
}
else
{
SiteDataEntities siteDB = new SiteDataEntities();
string path = page.PageKey;
Page parent = siteDB.Pages.Find(page.ParentPageId);
while (parent != null)
{
path = parent.PageKey + "/" + path;
parent = siteDB.Pages.Find(parent.ParentPageId);
if (parent.PageKey == "home") break;
}
return path;
}
}
答案 1 :(得分:1)
以前提出的解决方案仅适用于少量页面。 因为根据代码:
应用程序为每个站点页面生成并注册Route。结果,我们的网站数量至少与网站中的网页数量相同。您可能知道RouteModule必须通过路由检查每个路由以找到第一个并执行正确的处理程序,控制器,操作,视图......
还有另外两种方法可以解决这个问题:
您可以创建一个派生自RouteBase的类,并实现您需要的属性和方法:将url拆分为segment,使用pageid,path,parents等确定当前页面填充RouteValueDictionary
您可以使用custom rewrite provider自定义UrlRewriteModule。想要将所有请求URL从树基础结构转换为mvc默认路由:
{控制器} / {行动} / {ID}?路径= parentlevel1 / parent2 / parent3 /....
可以准备两种变体的90%相同的代码。 当你有不同的控制器时,该解决方案也很有用,正确的当前页面可以确定(通过页面数据:类型)