我已经建立了许多ASP.Net MVC网站,每个网站都有很多适合MVC控制器和动作的页面,还有一些页面实际上只是宣传册页面 - /为什么,/为什么/ ouradvantage,/ about等 - 没有真正功能的页面,只是一个视图,可能是一个布局,就是这样。
对于这些宣传册式的页面,我真的更喜欢只有View和一个很好的路线来找到它,所以我可以将/ why放在/Brochure/Why.cshtml或/Brochure/Why/Index.cshtml无论哪种方式,它都会被接受。我想避免使用愚蠢的控制器和动作(就像我过去一样)来处理这组URL和页面。
我如何在ASP.Net MVC项目中解决这个问题?这必须是一个普遍需要。
编辑:我如何以冗长的方式做到这一点的一个例子:
我可以使用标准MVC路由({controller} / {action} / {id})并向一堆无用的控制器发送垃圾邮件以获取我想要的URL和页面集。每次我想添加一个宣传册式(没有功能,只是一个View)页面时,我会添加一个Controller或Action,如下所示:
为什么选择控制器:
public class WhyController : Controller
{
public ViewResult Index()
{
return View();
}
public ViewResult OurAdvantage()
{
return View();
}
}
这会将View放在/ why和/ why / ouradvantage - 清除URL。如果我想要一个/ about页面,我可以添加另一个Controller,除了返回名为AboutController的View之外什么都不做。如果它有5个子页面,我可以向该控制器添加5个动作,所有这些动作除了返回视图外什么都不做。
如果MVC网站上的这些宣传册式的页面总共有100页,我会有相当多的不必要的控制器和动作都没有做任何事情。不是很干。我有兴趣将一个方法放在我的项目的一个文件夹中,并让它们可以访问(通过约定配置),干净的URL,如/ why和/ why / ouradvantage。
有几种让我接近的方法:
我可以放入一堆.cshtml页面并直接访问它们 - 但是我必须在URL中包含文件扩展名,而View文件本身必须位于根目录中。
我可以使用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个问题:
'〜/ Brochure / About.cshtml'的视图必须来自WebViewPage
答案 0 :(得分:1)
要映射单个页面RouteCollection.MapPageRoute
方法,可以使用。
routes.MapPageRoute("", "why", "~/Brochure/Why.aspx");
当然,您可以使用Razor视图引擎(.cshtml)而不是WebForms。
<德尔> Check MSDN documentation for some more details. 德尔>
更新2
你是对的,你将无法将其用于.cshtml页面。但是,您不需要使用路由来访问网页(.cshtml文件)。它足以创建文件,并省略URL中的扩展名。要实现所需的结构,您可以这样做:
web.config
并将webpages.Enabled
设置为true
。 (<add key="webpages:Enabled" value="true" />
)why
Index.cshtml
的MVC ViewPage。这可以从http://yoursite.com/why ouradvantages.cshtml
的MVC ViewPage。这可以从http://yoursite.com/why/ouradvantages @UrlData
集合查看有关此here的详情。有关网页的更多信息is also available on asp.net website。
如果由于某种原因您确实需要使用路由,则需要自定义RouteHandler。你可以find one implemented on Nuget。此程序包的用法示例为here。
<强>更新强>
如果您想避免手动添加每条路线,则几乎没有选择。
1)创建一个公约以识别宣传册页
您可以通过默认将网址设为宣传页,并将“非宣传册”页面隔离到特定部分来实现此目的:
routes.MapPageRoute("Default", "{brochurepage}", "~/Brochure/{brochurepage}.aspx");
// isolate non-brochure pages to "site" section
routes.MapRoute(
"",
"site/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
2)在一个集合中保留宣传册页面名称
List<string> brochurePages = new List<string>()
{ "about", "why", "contact" }; // add more pages here
....
foreach (var brochurePage in brochurePages)
routes.MapPageRoute("", brochurePage, "~/Brochure/" + brochurePage + ".aspx");
我必须非常具体地说明您在问题中提到的两个网址。要实现“/ why”和“/ why / ouradvantage”的路由,您将无法编写优雅的代码。这需要特殊处理。
答案 1 :(得分:0)
如果您的问题是您不希望为所有这些“愚蠢”的页面设置单独的控制器,我是否可以建议您创建一种逻辑方式将它们路由到单个控制器,然后基于正确的数据/视图呈现在路线上?
例如,您的网址可以显示为“/ Pages / Why / About”,您可以将其路由到您的网页控制器,它会收到“为什么”和“关于”作为参数,您可以相应地呈现您的内容。这有意义吗?