9

我有一个 ID 为的实体

public string ID {get;set;}    
activities/1

(来自 RavenDB)。

我在我的 ServiceStack AppHost 中注册了以下路由

Routes
    .Add<Activity>("/activities")
    .Add<Activity("/activities/{id}");

我正在使用主干应用程序向我的 REST 服务 POST 和 PUT。

开箱即用会发生什么:

  • id 属性被序列化为 json 为“activities/1”
  • id 属性被编码为“activities%2F1”的路由
  • ServiceStack 优先于基于 URL 的 id 属性,因此我的字符串获取直接对 RavenDb 没有用的编码值。

我知道的选项:

  • 将主干更改为发布到“/活动”并让 JSON 序列化器启动
  • 更改 RavenDb ID 生成以使用连字符而不是斜杠
  • 让我的 Id 属性在集合上解析编码的 %2F 并转换为斜杠

两者都有缺点,因为我要么在我的 API 中失去了 RESTful,这是不可取的,要么我不遵循 RavenDb 约定,这通常是明智的。另外,我个人偏好使用斜线。

所以我想知道在 servicestack 中是否有任何其他选项可以用来对涉及较少妥协的问题进行排序?序列化程序自定义或通配符路由都在我的脑海中......

4

2 回答 2

10

我对 ASP.Net WebAPI 也有同样的问题,所以我不认为这是一个 ServiceStack 问题,而只是在处理 REST URL 上的 Raven 样式 id 时普遍关心的问题。

例如,假设我查询GET: /api/users并返回如下结果:

[{
  Id:"users/1",
  Name:"John"
},
{
  Id:"users/2",
  Name:"Mary"
}]

现在我想获得一个特定的用户。如果我遵循纯 REST 方法,则会从该文档中收集 Id,然后将其传递到 url 的 id 部分。这里的问题是,这最终看起来 GET: /api/users/users/1不仅令人困惑,而且斜线妨碍了 WebAPI(和 ServiceStack)如何将 url 参数路由到操作方法。

我做出的妥协是仅从 URL 的角度将 id 视为整数。所以客户端调用GET: /api/users/1,我将我的方法定义为public User Get(int id).

很酷的部分是 Raven 的session.Load(id)重载可以采用完整的字符串形式或整数形式,因此您大部分时间都不必翻译。

如果你发现自己需要翻译 id,你可以使用这个扩展方法:

public static string GetStringIdFor<T>(this IDocumentSession session, int id)
{
  var c = session.Advanced.DocumentStore.Conventions;
  return c.FindFullDocumentKeyFromNonStringIdentifier(id, typeof (T), false);
}

调用它很简单session.GetStringIdFor<User>(id)。我通常只需要手动翻译,如果我正在使用 id 做一些事情,而不是立即加载文档。

我明白,通过翻译这样的 id,我打破了一些 REST 纯粹主义约定,但我认为在这种情况下这是合理的。我会对任何人提出的任何替代方法感兴趣。

于 2012-10-17T17:26:04.477 回答
0

我在使用 RavenDB 试用 Durandal JS 时遇到了这个问题。

我的解决方法是稍微更改 URL 以使其正常工作。所以在你的例子中:

GET /api/users/users/1

成为

GET /api/users/?id=users/1

从jQuery,这变成:

var vm = {};
vm.users = [];

$.get("/api/users/?" + $.param( { id: "users/1" })
  .done(function(data) {
      vm.users = data;
  });
于 2014-07-02T12:36:50.470 回答