2012-10-17 53 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; 
    });