ServiceStack Routing不适用于查询字符串

时间:2012-08-28 17:08:31

标签: routing servicestack

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

如果我配置这样的路线:

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

此请求成功。

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

如果我配置这样的路由(Business Analyst更喜欢生成的元数据)

        //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的请求成功?

感谢。

2 个答案:

答案 0 :(得分:34)

ServiceStack页面中解释了Your first website explained wiki中的部分路由:

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

仅匹配:

/hello/name

其中:

[Route("/hello")]

匹配:

/hello?Name=XXX

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

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

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

匹配:

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

Another good use-case for when to use wildcard routes

因此要匹配/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 REST服务,其中包含所有HTTP动词的实现,它会注册这些路由:

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. 当路由具有相同的权重时,顺序由服务中的操作位置或注册顺序(FIFO)决定
  5. 有关示例,请参阅Wiki上的Smart Routing部分。

    出色的表现

    Routing in MVC can be slow开始,当你拥有大量路由时,我认为值得指出ServiceStack的路由实现是通过哈希查找实现的,因此不会遇到MVC可能存在的线性性能回归问题。

答案 1 :(得分:1)

关注the answer in the other StackOverflow post,您可以尝试以下路线:

/Contacts/{Ids*}

并使用此请求类:

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

然后给定URL <service>/Contacts?Id=1&Id=2&Id=3 ServiceStack将使用以下字符串填充请求对象的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块中,以处理格式错误的查询字符串。