2013-02-18 40 views
1

我已经建立了一些ASP.Net MVC网站和他们每个人也有许多适合MVC的控制器和操作页面,和一些是网页真的只是宣传册页面 - /为什么,/为什么/ ouradvantage,/ about等 - 没有实际功能的页面,只是一个视图,也许是一个布局,就是这样。处理手册风格的网页在ASP.Net MVC

对于这些小册子样式的页面,我真的希望只有视图和一个很好的路径来找到它,所以我可以把/ why /宣传册/Why.cshtml或/ Brochure/Why/Index放在/ Why。 cshtml,无论哪种方式,它会被拿起很好。我想避免制作愚蠢的控制器和操作(就像我以前所做的那样)来处理这组URL和页面。

如何在ASP.Net MVC项目中解决这个问题?这一定是一个共同的需求。

编辑:

我可以使用标准的MVC路线({控制器}/{行动}/{ID})和垃圾邮件一堆无用的控制器来:我怎么能做到这一点的详细方式的例子获取我想要的一组网址和网页。每次我想添加一个小册子式(无功能,只是一个视图)页我想添加一个控制器或者动作是这样的:

为什么控制器:

public class WhyController : Controller 
{ 
    public ViewResult Index() 
    { 
     return View(); 
    } 

    public ViewResult OurAdvantage() 
    { 
     return View(); 
    } 
} 

这使得在浏览/为什么和/为什么/ ouradvantage - 干净的网址。如果我想要一个/关于页面,我可以添加另一个控制器,它什么都不做,但返回一个名为AboutController的View。如果它有5个子页面,我可以向该控制器添加5个动作,所有这些动作什么也不做,只是返回一个视图。

如果MVC网站,这些宣传册式的网页达说,100多页,我倒是有不少不必要的控制器和动作都做得真的没什么。不是很干。我对将视图放在项目的文件夹中的方式感兴趣,并且让它们可以在干净的URL(例如/ why和/ why/ouradivantage)中访问(通过约定配置)。

有迹象表明,让我靠近的几种方法:

我可以把一堆.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个问题:

  1. 它像我之前提到的那样对路由引擎进行了垃圾邮件处理 - 如果您有100页,则有100条路由。
  2. 传递路径如上似乎打乱了正常的剃刀管道 - 以这种方式访问​​一个页面让你这样的错误:

的观点在“〜/小册子/ About.cshtml”必须派生来自WebViewPage

+0

我不完全理解你想要的行为......请提供路线和结果行为的一些例子在您的文章 – 2013-02-18 21:34:52

+0

@DaveA更新包含的代码更清晰的例子。 – 2013-02-18 22:18:56

+0

我想我明白了。你愿意使用可互换的部分吗?这可以让路线传递部分名称。美丽是你的路由仍然会很好看,你将有多个控制器,每一个单一的视图和无数的谐音每个控制器的专用文件夹视图... – 2013-02-18 22:27:34

回答

1

要映射单个页面,可以使用RouteCollection.MapPageRoute方法。

routes.MapPageRoute("", "why", "~/Brochure/Why.aspx"); 

当然,你可以使用,而不是WebForms的Razor视图引擎(.cshtml)。

Check MSDN documentation for some more details.


更新2

你是对的,你将无法使用此为.cshtml网页。但是,您不需要使用路由来访问网页(.cshtml文件)。创建这些文件就足够了,并且省略了URL中的扩展。要实现您所需的结构,您可以这样做:

  • 您的Web项目必须允许网页呈现。要启用此功能,请转至web.config并将webpages.Enabled设置为true。 (<add key="webpages:Enabled" value="true" />
  • Web应用程序根目录下创建文件夹why
  • 加入MVC的ViewPage命名Index.cshtml。这将可从http://yoursite.com/why
  • 添加MVC查看页面命名为ouradvantages.cshtml。这将是访问从http://yoursite.com/why/ouradvantages
  • 您还可以使用@UrlData收集

检查更多有关这个here访问URL数据。有关网页的更多信息,请参见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"); 
扣住册页的名字

我必须非常具体,你在你的问题中提到的两个URL。要实现“/ why”和“/ why/ouradvantage”的路由,你将无法编写优雅的代码。这将需要特殊处理。

+0

事实上,后来我需要为每个小册子风格的页面做的MapPageRoute - 不太干。如果我有100个小册子风格的页面,我必须继续采取这些将这些MapPageRoute调用添加到RouteConfig.cs的额外步骤。这可能对路由引擎的性能没有帮助。 – 2013-02-18 21:48:32

+0

关键是将您引导到可用于执行此操作的ASP.NET扩展点。这是干的,因为我的例子是单页。对于多页面,1)提出一个约定来识别小册子页面或2)创建一个页面名称集合并在一个循环中调用'MapPageRoute'。我会用一个例子扩展我的答案 – 2013-02-18 21:52:21

+0

这更接近了;您提到的集合可以像Directory.FindFiles(Server.MapMath(“〜/ Brochure”),“* .cshtml”)那样生成。如果重复调用MapPageRoute只是扩展一个简单的哈希表,性能影响可以忽略不计。然而,关于子页面的注意事项成为一个问题,因为允许〜\ why \ index.cshtml或〜\ why.cshtml的简单性。尽管更接近。 – 2013-02-18 22:26:20

0

如果你的问题是,你不想对所有这些“傻”的页面单独的控制器,可我建议你创建一个符合逻辑的方式来它们路由到一个单一的控制器,然后使正确的数据/图基于路线?例如,您的网址可能会显示“/ Pages/Why/About”,您可以将其路由到您的网页控制器,它会接收“为什么”和“关于”作为参数,并且您可以相应地呈现您的内容。那有意义吗?

+0

这是我过去采取的哈克式方法,我试图避免,因为它似乎像任何MVC项目可能需要这些类型的页面,并将它们连接起来应该是微不足道的。看起来它是微不足道的 - 如果它们是.aspx页面,但如果你想使用Razor语法 - 它需要这个混乱。我会用代码示例发布更长的答案。 – 2013-02-18 23:49:39

+0

我已经更新了我的问题以包含这种解决方案的一个例子 - 不幸的是,路由引擎可能太垃圾。 – 2013-02-19 00:25:23