【发布时间】:2013-02-18 21:32:43
【问题描述】:
我已经建立了许多 ASP.Net MVC 站点,每个站点中都有许多适合 MVC 控制器和操作的页面,以及一些实际上只是小册子页面的页面 - /why、/why /ouradvantage、/about 等 - 没有真正功能的页面,只是一个视图,也许是一个布局,仅此而已。
对于这些小册子风格的页面,我真的更喜欢只有视图和一个好的路线来找到它,所以我可以把 /why 放在 /Brochure/Why.cshtml 或 /Brochure/Why/Index.cshtml无论哪种方式,它都会被很好地捡起。我想避免使用愚蠢的控制器和动作(就像我过去所做的那样)来处理这组 URL 和页面。
如何在 ASP.Net MVC 项目中解决这个问题?这一定是一个共同的需求。
编辑:我如何以详细方式执行此操作的示例:
我可以使用标准的 MVC 路由 ({controller}/{action}/{id}) 并发送一堆无用的控制器来获取我想要的 URL 和页面集。每次我想添加一个小册子样式(没有功能,只是一个视图)页面时,我都会添加一个控制器或动作,如下所示:
为什么选择控制器:
public class WhyController : Controller
{
public ViewResult Index()
{
return View();
}
public ViewResult OurAdvantage()
{
return View();
}
}
这会在 /why 和 /why/ouradvantage 放置一个视图 - 干净的 URL。如果我想要一个 /about 页面,我可以添加另一个控制器,它只返回一个名为 AboutController 的视图。如果它有 5 个子页面,我可以向那个控制器添加 5 个动作,所有这些动作都只返回一个视图。
如果 MVC 站点中的这些小册子式页面总计 100 页,那么我将有相当多的无用的控制器和动作,它们实际上什么都不做。不是很干。我对一种方法很感兴趣,只需将视图放在我的项目中的一个文件夹中,并让它们可以访问(通过约定配置),在 /why 和 /why/ouradvantage 等干净的 URL 处。
有几种方法可以让我接近:
我可以放入一堆 .cshtml 页面并直接访问它们 - 但是我必须在 URL 中包含文件扩展名,并且视图文件本身必须位于根目录中。
我可以使用 ASP.Net 区域为这些区域定义一个区域,但是所有小册子样式的页面都必须位于至少一个 URL 段深处,并且我仍然遇到上述 URL 中文件扩展名的问题。
我可以定义许多疯狂的路线。
我怀疑这经常出现在具有少量或大量此类小册子样式页面的 MVC 项目中 - 似乎应该有一种干净的方法来做到这一点。
编辑:垃圾邮件路由引擎的蹩脚解决方案。
创建一个映射路由的类,例如:
public static void MapRoutes(RouteCollection routes, string appRoot, string path)
{
if (!path.Contains("~/"))
throw new NotSupportedException("Pages path must be virtual (use ~/ syntax).");
var physicalPath = appRoot + path.Substring(2).Replace("/", "\\");
var dir = new DirectoryInfo(physicalPath);
var pages = dir.GetFiles("*.cshtml", SearchOption.AllDirectories);
int rootLength = appRoot.Length;
var rootParsed = pages.Select(p => "~/" + p.FullName.Substring(rootLength).Replace("\\", "/"));
int folderPathLength = path.Length + 1;
var mapped = rootParsed.Select(p => new {
Url = p.Substring(folderPathLength, p.Length - 7 - folderPathLength),
File = p
});
var routedPages = mapped.Select(m => routes.MapRoute(
name: m.Url,
url: "{*url}",
defaults: new { path = m.File, Controller = "Brochure", Action = "Catchall" },
constraints: new { url = m.Url }
)).ToArray();
}
你可以在 RouteConfig 中这样调用它:
BrochureRoute.MapRoutes(routes, Server.MapPath("~/"), "~/Brochure");
这显然将所有这些页面映射到 BrochureController,您也需要它:
public class BrochureController : Controller
{
public ViewResult Catchall(string path)
{
return View(path);
}
}
2 个问题:
- 正如我所提到的,它会向路由引擎发送垃圾邮件 - 如果您有 100 个页面,那么您就有 100 个路由。
- 通过上述路径似乎会扰乱正常的 Razor 管道 - 以这种方式访问页面会出现如下错误:
'~/Brochure/About.cshtml' 处的视图必须派生自 WebViewPage
【问题讨论】:
-
我不完全理解您想要的行为...请在您的帖子中提供更多路线示例和结果操作
-
@DaveA 更新为包含更清晰的代码示例。
-
我想我明白了。您愿意使用可互换的零件吗?这你可以有一个传递部分名称的路线。美妙之处在于您的路线仍然看起来不错,并且您将拥有多个控制器,每个控制器都有一个视图,并且每个控制器的专用视图文件夹中有无数的部分......
标签: asp.net-mvc razor routing asp.net-mvc-routing