17

我有一个使用 ServiceStack 构建的简单 REST 服务。

如果我这样配置路由:

        //register user-defined REST-ful urls
        Routes
            .Add<Contact>("/Contacts")
            .Add<Contact>("/Contacts/{ContactId}")

此请求成功。

http://<server>:59557/Contacts?ContactId=9999 //Works

如果我像这样配置路由(业务分析师更喜欢生成的元数据)

        //register user-defined REST-ful urls
        Routes
            .Add<UpdateContact>("/UpdateContact", "PUT")
            .Add<CreateContact>("/CreateContact", "POST")
            .Add<GetContact>("/Contacts/{ContactId}", "GET")

http://<server>:59557/Contacts/9999           //Works
http://<server>:59557/Contacts?ContactId=9999 //Fails, Handler for request not found

如何配置第二个示例中的路由,以便对 /Contacts?ContactId=9999 的请求成功?

谢谢。

4

2 回答 2

34

您的第一个网站解释 wiki页面上解释了ServiceStack中的一些路由:

[Route("/hello/{Name}")]

仅匹配:

/hello/name

然而:

[Route("/hello")]

火柴:

/hello?Name=XXX

注意:QueryString、FormData 和 HTTP 请求正文不是 Route 的一部分(即只有 /path/info 是),但除了每个 Web 服务调用之外,它们都可以用于进一步填充 Request DTO。

并使用带有通配符路径的路由,例如:

[Route("/hello/{Name*}")]

火柴:

/hello
/hello/name
/hello/my/name/is/ServiceStack

何时使用通配符路由的另一个很好的用例

所以要匹配/Customers?Key=Value/Customers/{Id}你需要为这两个路由注册匹配的路由,例如:

Routes
    .Add<GetContact>("/Contacts", "GET")
    .Add<GetContact>("/Contacts/{ContactId}", "GET")

如何为所有服务自动注册基于约定的路线

与此相关的还有通过AddFromAssembly扩展方法注册自动路由,其中​​这个单一调用:

Routes.AddFromAssembly(typeof(MyService).Assembly)

遍历并扫描您的所有服务(在指定的程序集中)并根据您已实现的所有 HTTP 方法注册基于约定的路由。例如,如果您的GetContactUpdateContact服务具有Id属性,它将自动注册以下路由:

Routes
    .Add<GetContact>("/Contacts", "GET")
    .Add<GetContact>("/Contacts/{Id}", "GET")
    .Add<UpdateContact>("/Contacts", "POST PUT")
    .Add<UpdateContact>("/Contacts/{Id}", "POST PUT")

如果您只有一个Contacts包含所有 HTTP 动词实现的 REST 服务,它将注册这些路由:

Routes
    .Add<Contacts>("/Contacts", "GET POST PUT DELETE PATCH")
    .Add<Contacts>("/Contacts/{Id}", "GET POST PUT DELETE PATCH")

路由解析顺序

这在New API Design wiki上有更详细的描述,但用于选择路线的权重基于:

  1. 首先使用任何精确的文字匹配
  2. 精确动词匹配优于所有动词
  3. 路线中的变量越多,它的权重就越小
  4. 当Routes具有相同的权重时,顺序由Action在服务中的位置或注册顺序(FIFO)决定

有关示例,请参阅wiki 上的智能路由部分。

很棒的演出

由于当您拥有大量路由时,MVC 中的路由可能会很慢,因此我认为值得指出 ServiceStack 的路由实现是通过哈希查找实现的,因此不会遭受 MVC 可能遇到的线性性能回归问题。

于 2012-08-28T18:39:49.677 回答
1

按照其他 StackOverflow 帖子中的答案,您可以尝试这条路线:

/Contacts/{Ids*}

并使用这个请求类:

public class ContactRequest { public string Ids { get; set; } }

然后给定 URL,<service>/Contacts?Id=1&Id=2&Id=3ServiceStack 将Ids使用以下字符串填充请求对象的属性:

Id=1&Id=2&Id=3

然后您可以解析为 ID 列表,例如

public object Get(ContactRequest request)
{
    var idPairs = request.Ids.Split("&");
    var ids = new List<string>();
    foreach (var idPair in idPairs)
    {
        ids.Add(idPair.Split("=")[1];
    }
    // ... do something with your ids now ...
    // ... return results ...
}

当然,您可能还希望将整个 ID 解析逻辑包装在一个try...catch块中以处理格式错误的查询字符串。

于 2013-07-12T15:12:56.520 回答