2012-10-17 54 views
9

我有一个实体的ServiceStack路由与ravendb IDS

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

的ID(它来自RavenDB)。

我注册了以下路线在我ServiceStack APPHOST

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

我使用主干应用POST和PUT到我的REST服务。

出的即装即用,会发生什么:

  • id属性被序列化到JSON作为
  • id属性被编码成是“活动%2F1”路线“活动/ 1”
  • ServiceStack优先考虑基于URL的id属性,所以我的字符串获得了直接对RavenDb无用的编码值。

的选择我所知道的:

  • 更改骨干张贴到“/活动”,让JSON串行器踢
  • 变化RavenDb ID生成使用连字符,而不是斜线
  • 让我Id属性解析对集编码为%2F和转换成斜线

两人都在我要么失去RESTfuln缺点在我的API中,这是不受欢迎的,或者我不遵循RavenDb惯例,这些惯例通常是明智的狐狸。另外,我个人喜欢斜线。

所以我想知道是否有任何其他选项在服务栈中,我可以用来排序这个问题涉及较少的妥协?无论是串行器定制或通配符路由在我的脑海....

回答

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纯化约定,但我认为这是合理的给定的情况下。我会对任何人提出的任何替代方法感兴趣。

+0

感谢这个马特。那么你是从GET返回一个整数ID:/ api/users? – Chris

+0

不,我发现它太笨拙操纵结果集,所以我只是返回完整的字符串Id。客户端应用程序保留完整的字符串ID,但是当它使用id生成一个url时,它会使用类似id.split(“/”)[1] –

0

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

我的解决方法是稍微更改网址以使其起作用。因此,在你的例子:

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; 
    });