路由片段约束

路由片段约束允许你给路由片段使用一个特定的约束。应用约束到片段仅需要在要约束的名称后添加一个:。

Get["/intConstraint/{value:int}"] = parameters => "Value " + parameters.value + " is an integer.";

上面的结果是路由的value片段只接受×××数据


下面是预定义好的约束:

  • int - Allows only Int32 (int) values.

  • long - Allows only Int64 (long) values.

  • decimal - Allows only decimal values.

  • guid - Allows only GUID values.

  • bool - Allows only boolean values.

  • alpha - Allows only values containing alphabetical character.

  • datetime - Allows only date values, optionally containing time.

  • datetime(format) (Added in 0.22) - Allows only date and/or time values with the specified format. For format values, seeCustom Date and Time Format Strings

  • min(minimum) - Allows only integer values with the specified minimum value.

  • max(maximum) - Allows only integer values with the specified maximum value.

  • range(minimum, maximum) - Allows only integer values within the specified range. (Between minimum and maximum)

  • minlength(length) - Allows only values longer than the specified minimum length.

  • maxlength(length) - Allows only values shorter that the maximum length.

  • length(minimum, maximum) - Allows only values with length within the specified range. (Between minimum and maximum)

  • version (Added in 1.2) - Allows only Version values, e.g. 1.2.0.

自定义约束

你也可以实现自己的自定义约束。很容易通过实现 IRouteSegmentConstraint, Nancy可以自动识别自定义约束, SDHP-style。 你也可以继承下面的工具类实现:

  • RouteSegmentConstraintBase<T> - 名称约束的基类。

  • ParameterizedRouteSegmentConstraintBase<T> - 可接收参数的名称约束的基类。

例子

邮件约束的实现示例 (although very simplified):

public class EmailRouteSegmentConstraint : RouteSegmentConstraintBase<string>
{    public override string Name
    {        get { return "email"; }
    }    
    protected override bool TryMatch(string constraint, string segment, out string matchedValue)
    {        if (segment.Contains("@"))
        {
            matchedValue = segment;            return true;
        }

        matchedValue = null;        return false;
    }
}

用法:

Get["/profile/{value:email}"] = parameters => "Value " + parameters.value + " is an e-mail address.";

这个路由符合一个必须包含@符号的约束。 传入路由的值通过matchedValue out 参数返回。

资源

请神魂颠倒去查看 Constraints Sample Project(约束示例项目) 的一些示例项目 或者 看一眼 existing constraint implementations(已经存在的约束的实现)。


扩展资源: 自定义路由的实现(E文)

http://www.philliphaydon.com/2013/04/nancyfx-implementing-your-own-routing/


选择调用正确路由的秘籍

There are a couple of gotchas you should be aware of when it comes to the default behavior, in Nancy, for selecting which route to invoke for a request. It sounds easy enough, you pick the one that matches the MethodPattern and Condition of the request, right? In the simplest case that is true and how it is selected, but what if things are a bit more complicated?

You could, for example, have two routes with patterns that would capture the same request under certain circumstances. These two routes could either be defined in the same module or split across several modules.

Turns out it’s not complicated after all, you just need to remember a couple of things

  1. The order in which modules are loaded are non-deterministic in between application start-ups

  2. Routes in a given module are discovered in the order in which they are defined

  3. If there are several possible matches, the most specific match, i.e the route pattern that has the highest number of matching literal segments and fewest capture segments

  4. If two, or more, routes are equal matches to a request, the first one is selected and which one this is depends on the module load order and the route order inside of the modules


疯狂的路由

Below are some samples of what routes in Nancy can look like. They cover some of the possible usages, but not all of them.

// would capture routes like /hello/nancy sent as a GET request
Get["/hello/{name}"] = parameters => {    
    return "Hello " + parameters.name;
};

// would capture routes like /favoriteNumber/1234, but not /favoriteNumber/asdf as a GET request
Get["/favoriteNumber/{value:int}"] = parameters => {
    return "So your favorite number is " + parameters.value + "?";
};

// would capture routes like /products/1034 sent as a DELETE request
Delete[@"/products/(?<id>[\d]{1,7})"] = parameters => {
    return 200;
};

// would capture routes like /users/192/add/moderator sent as a POST request
Post["/users/{id}/add/{category}"] = parameters => {
    return HttpStatusCode.OK;
};