NancyFX捕获所有路由

17

NancyFX是否支持像ASP.NET MVC中的“Catch All”路由? 我需要一个基本上匹配每个URL的路由。 这对于构建单页应用程序非常方便。

这种情况有可能吗?

4个回答

17

在 Nancy 版本 0.23.2 中测试通过

Get[@"/(.*)"] 对我来说不起作用,它无法捕获 "/""/foo/bar" 或更长的路由。看起来定义一个根 URL 的 Get["/"] 路由是必须的,没有其他方法可以捕获它(尝试过 Get["{uri*}"])。这是我最终定义路由的方式(请记住,我正在为 Angular 应用程序执行此操作):

Get["/views/{uri*}"] = _ => { return "A partial view..."; };
Get["/"] =
Get["/{uri*}"] = _ =>
{
    var uri = (string)_.uri;// The captured route
    // If you're using OWIN, you can also get a reference to the captured route with:
    var environment = this.Context.GetOwinEnvironment();// GetOwinEnvironment is in the 'Nancy.Owin' namespace
    var requestPath = (string)environment["owin.RequestPath"];
    return View["views/defaultLayout.html"];
};

了解模式打分很重要。路由模式有权重,如果两个路由匹配同一网址段,得分高的胜出。捕获所有模式的权重是0,即使/views/{uri*}路由模式也是捕获所有的情况,但它以字面量开始,其权重为10000,因此它将在所有以/views开头的路由中胜出。

这里有关于访问Owin环境变量的更多信息。请注意,捕获的uri变量和requestPath会略有不同。 requestPath/开头,而uri变量则没有。此外,如果匹配的路由模式是Get ["/"],则uri将为nullrequestPath将为"/"

Views路由将根据URL路径返回部分html文件,而所有其他路由将返回默认的Layout页面,该页面将引导SPA。


11

可以,使用正则表达式

Get[@"/(.*)"] = parameters => {
    return View["viewname", parameters];
};

但是,如果你使用NancyFX构建单页面应用程序,你实际上不需要它-你只需在所有路由逻辑中使用Get和Post,仍然可以拥有一个单页面应用程序。


2
谢谢,它起作用了。我为什么需要它,因为我有启用push state的Backbone驱动SPA。 然后我路由到SPA内部的localhost:8080 / some / 1页面 - 一切都很正常。 但是,我可以复制URL并将其发送给朋友,他尝试打开时会收到404错误。 因此,我需要捕获所有路由并处理master.html视图,重置由JS构建。 - Alexander Beletsky
1
你可以在这里看到代码的详细信息:https://github.com/alexanderbeletsky/candidate - Alexander Beletsky
1
您也可以使用贪婪段(Greedy Segments) https://github.com/NancyFx/Nancy/wiki/Defining-routes#pattern - boop

8
对于那些 @synhershko 的解决方案不起作用的人,以下是一个更新过的答案。请尝试:
Get[@"^(.*)$"] = parameters => {
    return "hi";
};

这将捕获除主页以外的所有路径。我不确定在Angular的上下文中是否会起作用,但这对我来说在尝试使用只有一个处理程序的简单服务器时有效。


2
这是 NancyFx > 2.0 的答案。 - Jason

3

@synhershko提供的答案对我没有用。它无法处理/users/2或任何其他包含更多段的路由。

以下代码在我的机器上可以工作;):

public class IndexModule : NancyModule
{
    dynamic IndexPage() { return View["Index"]; }

    public IndexModule()
    {
        Get["/"] = _ => { return IndexPage(); };
        Get["/(.*)"] = _ => { return IndexPage(); };
        Get["/(.*)/(.*)"] = _ => { return IndexPage(); };
        Get["/(.*)/(.*)/(.*)"] = _ => { return IndexPage(); };
    }
}

我的解决方案并不完美,因为它不能匹配所有内容。我重复了和我的最长Angular路由中一样多的'/(.*)'。


1
IndexPage方法应返回“Negotiator”,这就是View[...]返回的内容。我还会传递参数变量以便访问它:public Negotiator GetIndexPage(dynamic _) {...}; 然后你可以在所有方法中引用它:Get["/"] = IndexPage; 等等...或者只需让它们通过而不定义IndexPage方法:Get["/"] = Get["/(.*)"] = ... = _ => { ... }; 但我建议完全避免使用多重catch-all,并使用Get["/"] = Get["/{uri*}"] = _ => {...};有关详细信息,请参见我的答案。 - nwayve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接