我已经建立了许多 ASP.Net MVC 站点,每个站点中都有许多适合 MVC 控制器和操作的页面,以及一些实际上只是小册子页面的页面 - /why、/why/ouradvantage、 /about 等 - 没有真正功能的页面,只是一个视图,也许是一个布局,仅此而已。
对于这些小册子风格的页面,我真的更喜欢只有 View 和一个很好的 Route 来找到它,所以我可以把 /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 页,那么我将有相当多的无用的控制器和动作,它们实际上什么都不做。不是很干。我对一种将视图放在我的项目中的文件夹中并让它们访问的方法很感兴趣(通过约定配置),在干净的 URL 上,如 /why 和 /why/ouradvantage。
有几种方法可以让我接近:
我可以放入一堆 .cshtml 页面并直接访问它们——但是我必须在 URL 中有文件扩展名,并且视图文件本身必须位于根目录中。
我可以使用 ASP.Net 区域为这些定义一个区域,但是所有小册子样式的页面都必须至少位于一个 URL 段深处,并且我仍然遇到上述 URL 中文件扩展名的问题。
我可以定义一些疯狂的路线。
我怀疑这经常出现在具有少量或大量这些 Brochure 样式页面的 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 派生