ServiceStack 路由不适用于查询字符串 [英] ServiceStack Routing does not work with querystring

查看:16
本文介绍了ServiceStack 路由不适用于查询字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如果我这样配置路由:

//注册用户定义的 REST-ful url路线.Add("/Contacts").Add("/Contacts/{ContactId}")

此请求成功.

http://:59557/Contacts?ContactId=9999//有效

<小时>

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

//注册用户定义的 REST-ful url路线.Add("/UpdateContact", "PUT").Add("/CreateContact", "POST").Add("/Contacts/{ContactId}", "GET")http://:59557/Contacts/9999//有效http://<server>:59557/Contacts?ContactId=9999//失败,未找到请求的处理程序

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

谢谢.

解决方案

ServiceStack 中的一些路由在你的第一个网站解释维基页面上有解释:

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

仅匹配:

/hello/name

其中:

[Route("/hello")]

匹配:

/hello?Name=XXX

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

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

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

匹配:

/hello/你好/名字/hello/my/name/is/ServiceStack

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

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

路线.Add("/Contacts", "GET").Add("/Contacts/{ContactId}", "GET")

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

与此相关的是通过 AddFromAssembly 扩展方法,这里单调用:

Routes.AddFromAssembly(typeof(MyService).Assembly)

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

路线.Add("/Contacts", "GET").Add("/Contacts/{Id}", "GET").Add("/Contacts", "POST PUT").Add("/Contacts/{Id}", "POST PUT")

如果你只有一个 Contacts REST 服务和所有 HTTP 动词的实现,它会注册这些路由:

路线.Add("/Contacts", "GET POST PUT DELETE PATCH").Add("/Contacts/{Id}", "GET POST PUT DELETE PATCH")

路由解析顺序

这在 新 API 设计 wiki 中有更详细的描述,但是用于选择路线的权重基于:

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

请参阅维基上的智能路由部分以获取示例.>

出色的表现

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

I have a simple REST service built with ServiceStack.

If I configure the routes like this:

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

This request succeeds.

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


If I configure the routes like this (Business Analyst prefers the generated metadata)

        //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

How can I configure the routes in the second sample so that a request to /Contacts?ContactId=9999 will succeed?

Thanks.

解决方案

Some of the Routing in ServiceStack is explained on the Your first website explained wiki page:

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

only matches:

/hello/name

where as:

[Route("/hello")]

matches:

/hello?Name=XXX

Note: The QueryString, FormData and HTTP Request Body isn't a part of the Route (i.e. only the /path/info is) but they can all be used in addition to every web service call to further populate the Request DTO.

and using a route with a wild card path like:

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

matches:

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

Another good use-case for when to use wildcard routes.

So to match /Customers?Key=Value and /Customers/{Id} you need to register matching routes for both these routes, e.g:

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

How to Auto Register Convention-based Routes for all services

Also related to this is registering Auto routes via the AddFromAssembly extension method, where this single call:

Routes.AddFromAssembly(typeof(MyService).Assembly)

Goes through and scands all your services (in the Assemblies specified) and registers convention-based routes based on all the HTTP methods you have implemented. E.g. if your GetContact and UpdateContact services had Id properties it would automatically register the following routes:

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

And if you just had a single Contacts REST Service with implementations for all the HTTP Verbs it would register these routes:

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

Routing Resolution Order

This is described in more detail on the New API Design wiki but the weighting used to select a route is based on:

  1. Any exact Literal Matches are used first
  2. Exact Verb match is preferred over All Verbs
  3. The more variables in your route the less weighting it has
  4. When Routes have the same weight, the order is determined by the position of the Action in the service or Order of Registration (FIFO)

See the Smart Routing section on the wiki for examples.

Great Performance

Since Routing in MVC can be slow when you have a large number of Routes, I think it's worthwhile pointing out ServiceStack's Routing implementation is implemented with hash lookups and so doesn't suffer the linear performance regression issues you might have had with MVC.

这篇关于ServiceStack 路由不适用于查询字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆