2012-10-17 6 views
9

Ich habe eine Einheit mit der IDServiceStack Routing mit RavenDB ids

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

(die aus RavenDB kommt).

Ich Registrierung die folgenden Routen in meinem ServiceStack AppHost

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

ich ein Rückgrat App POST bin mit und PUT meinem REST-Service.

Was out-of-the-box passiert:

  • id-Eigenschaft in die json als "Aktivitäten/1" serialisiert wird
  • id-Eigenschaft wird in Route codiert als "-Aktivitäten% 2F1"
  • ServiceStack gibt der URL-basierten ID-Eigenschaft den Vorrang, so dass meine Zeichenfolge den codierten Wert erhält, der RavenDb nicht direkt nutzt.

Die Optionen Ich bin mir dessen bewusst:

  • ändern Rückgrat, um es zu "/ Aktivitäten" und lassen Sie die JSON Serializer Kick in
  • ändern RavenDB ID Generation Bindestriche eher zu verwenden als schlitzt
  • Make my Id-Eigenschaft Parsing für die codierte% 2F am Set und konvertieren entweder einen Schrägstrich

Beide haben den Nachteil, daß ich verlieren RESTfuln Das ist in meiner API unerwünscht, oder ich folge nicht den RavenDb-Konventionen, die normalerweise außerhalb des Fuchses sinnvoll sind. Außerdem habe ich eine persönliche Vorliebe für Schrägstriche.

Also frage ich mich, ob es weitere Optionen in Servicestack gibt, die ich verwenden könnte, um dieses Problem zu lösen, die weniger Kompromisse beinhalten? Entweder Serializer-Anpassung oder Platzhalter-Routing sind in meinem Kopf ....

Antwort

10

Ich habe das gleiche Problem mit ASP.Net WebAPI, so dass ich denke nicht, dass dies so ein Problem ServiceStack ist, sondern nur ein generelles Anliegen mit dem Umgang mit Raven-Stil-IDs auf einer REST-URL.

Zum Beispiel lassen Sie uns sagen, dass ich Abfrage GET: /api/users und zurück ein Ergebnis wie:

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

Jetzt möchte ich einen bestimmten Benutzer erhalten. Wenn ich dem reinen REST-Ansatz folge, würde die ID aus diesem Dokument stammen, und dann würde ich sie im ID-Teil der URL übergeben. Das Problem hier ist, dass dies am Ende aussieht wie GET: /api/users/users/1, die nicht nur verwirrend ist, aber der Schrägstrich behindert, wie WebAPI (und ServiceStack) URL-Parameter zu Aktionsmethoden leiten.

Der Kompromiss, den ich gemacht habe, bestand darin, die ID nur aus der Sicht der URL als Ganzzahl zu behandeln. Also ruft der Client GET: /api/users/1, und ich definiere meine Methode als public User Get(int id).

Der coole Teil ist, dass Raven session.Load(id) Überladungen hat, die entweder die vollständige Zeichenkette oder die Ganzzahlform annehmen, so dass Sie die meiste Zeit nicht übersetzen müssen.

Wenn Sie sich selbst finden, um die ID zu übersetzen, können Sie diese Erweiterung Methode verwenden:

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

Aufruf als session.GetStringIdFor<User>(id) einfach ist. Normalerweise muss ich nur manuell übersetzen, wenn ich etwas mit der ID mache, anstatt sofort ein Dokument zu laden.

Ich verstehe, dass durch die Übersetzung der IDs, dass ich einige REST puristische Konventionen brechen, aber ich denke, dass dies angesichts der Umstände vernünftig ist. Ich wäre an irgendwelchen alternativen Ansätzen interessiert, mit denen jeder aufwartet.

+0

Vielen Dank für diesen Matt. Also gibst du eine Integer ID von GET zurück:/api/users? – Chris

+0

Nein, ich fand es zu ungeschickt, die Ergebnismenge zu manipulieren, daher gebe ich nur die vollständige Zeichenkette Id zurück. Die Client-App behält die vollständige String-ID bei, aber wenn sie eine URL mit einer ID erstellt, entfernt sie den Frontteil mit etwas wie id.split ("/") [1] –

0

Ich hatte dieses Problem, wenn ich Durandal JS mit RavenDB ausprobierte.

Meine Problemumgehung war, die URL sehr leicht zu ändern, damit sie funktioniert. Also in Ihrem Beispiel:

GET /api/users/users/1 

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

Von jQuery wird daraus:

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

$.get("/api/users/?" + $.param({ id: "users/1" }) 
    .done(function(data) { 
     vm.users = data; 
    });