如何在MVC路线中组合CatchAll和EndsWith?

时间:2012-04-11 21:35:58

标签: asp.net-mvc-3

以下路由将匹配BasePath下面的任何文件夹结构:

http://BasePath/{*SomeFolders}/ 

如何创建另一条匹配同一BasePath结构下任何zip文件的路由?

我试过了......

http://BasePath/{*SomeFolders}/{ZipFile}

...但

错误

包含多个部分的路径段(例如文字部分或参数)不能包含catch-all参数。 参数名称:routeUrl

我该如何处理?

*的 更新 *

原始要求实际上是有缺陷的。 {ZipFile}将匹配最后一节,无论它包含什么。 (文件或文件夹)

实际上我相信我想要匹配的路线模式应该是:

http://BasePath/{*SomeFolders}/{ZipFile}.zip

3 个答案:

答案 0 :(得分:6)

这似乎是约束的答案。

    routes.MapRoute( _
        "ViewFile", "BasePath/{*RestOfPath}", _
        New With {.controller = "File", .action = "DownloadFile"}, _
        New With {.RestOfPath = ".*\.zip"}
    )
    routes.MapRoute( _
        "ViewFolder", "BasePath/{*RestOfPath}", _
        New With {.controller = "Folder", .action = "ViewFolder"} _
    )

或者喜欢C#的人

    routes.MapRoute( 
        "ViewFile", "BasePath/{*RestOfPath}", 
        new {controller = "File", action = "DownloadFile"}, 
        new {RestOfPath = @".*\.zip"}
    );
    routes.MapRoute( 
        "ViewFolder", "BasePath/{*RestOfPath}", 
        new {controller = "Folder", action = "ViewFolder"} 
    );

(呃,我认为是对的)

相同的路由被注册两次,第一个变体被赋予了RestOfPath参数应以“.zip”结尾的附加约束

我理解使用IRouteConstraint的衍生物也可以使用自定义约束。

答案 1 :(得分:4)

抓住网址中的任何地方 - 正是您需要的

我已经编写了这样的Route课程,可以让您完全按照自己的描述进行操作。它允许您将catch-all段作为路径定义中的第一个段(或实际上的任何其他段)。它允许您将路线定义为:

"BasePath/{*SomeFolders}/{ZipFile}"

my blog post上详细描述了整个内容,您可以在其中找到此Route类的代码。

其他信息

根据添加的信息,我仍然宁愿使用第一个路径定义,它不会将路径段参数中的文件扩展名排除在外,而是为最后一个段添加约束

"[a-zA-Z0-9_]+\.zip"

因此,路由仍应如上所述在我的答案中定义,但ZipFile的约束应如先前所述定义。这将使我的特殊路线像现在一样开箱即用。

还要使其适用于其他路由分隔符(例如示例中的 dot )代码应该进行相当大的更改,但是如果您知道路由的工作方式非常好,则可以将其更改为方式。

但我建议你保持简单并添加约束。

答案 2 :(得分:1)

正如错误所说,你的捕获必须是你路线中的最后一个参数。

要获取ZipFile部分,您必须从SomeFolders catchall解析它:

public ActionResult MyAction(string SomeFolders)
{
    // parse the ZipFile out from the SomeFolders argument
}

所以如果你有/folder1/folder2/folder3/file.zip,你可以这样做:

var zipFile = SomeFolders.SubString(SomeFolders.LastIndexOf("/") + 1);