2012-10-17 17 views
9

ho un'entità con un ID diServiceStack Routing con ids RavenDB

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

(che viene da RavenDB).

sto registrando i seguenti percorsi nel mio ServiceStack AppHost

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

sto usando un'applicazione spina dorsale per POST e PUT al mio servizio REST.

Cosa succede out-of-the-box:

  • proprietà id viene serializzato in JSON come "attività/1"
  • proprietà
  • id viene codificato in rotta come "attività% 2F1"
  • ServiceStack fornisce la precedenza alla proprietà ID basata su URL, quindi la mia stringa ottiene il valore codificato che non è direttamente utilizzabile da RavenDb.

Le opzioni che sono a conoscenza di:

  • Change spina dorsale di inviare a "/ attività" e lasciare che il calcio JSON Serialiser in
  • generazione
  • Change RavenDB ID da usare trattini anziché barre
  • fare il mio ID proprietà parse per la 2F% codificato sul set e convertire in una barra

Entrambi hanno svantaggi che mi sia perso RESTfuln nella mia API, che è indesiderabile, o non seguo le convenzioni RavenDb, che di solito sono ragionevoli out-of-the-fox. Inoltre, ho una preferenza personale per avere le barre.

Quindi mi chiedo se ci sono altre opzioni in servicestack che potrei usare per ordinare questo problema che comporta meno compromessi? La personalizzazione di Serialiser o il routing con caratteri jolly sono nella mia mente ....

risposta

10

Ho lo stesso problema con Web.AP.A., quindi non penso che questo sia un problema di ServiceStack, ma solo una preoccupazione generale con la gestione con gli ID stile Raven su un URL REST.

Per esempio, diciamo che interrogo GET: /api/users e restituire un risultato simile:

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

Ora voglio ottenere un utente specifico. Se seguo un approccio REST puro, l'ID verrebbe raccolto da questo documento e quindi lo passerei nella parte id dell'URL. Il problema qui è che questo appare come GET: /api/users/users/1 che non è solo confuso, ma la barra si interrompe su come WebAPI (e ServiceStack) instradano i parametri url ai metodi di azione.

Il compromesso che ho fatto è stato quello di trattare l'id come un numero intero solo dalla prospettiva dell'URL. Quindi il client chiama GET: /api/users/1 e definisco il mio metodo come public User Get(int id).

La parte interessante è che il session.Load(id) di Raven ha sovraccarichi che richiedono il formato di stringa completo o il modulo intero, quindi non è necessario tradurre la maggior parte del tempo.

Se vi trovate a dover tradurre il id, è possibile utilizzare questo metodo di estensione:

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

Calling è semplice come session.GetStringIdFor<User>(id). Di solito devo solo tradurre manualmente se sto facendo qualcosa con l'id tranne che caricando immediatamente un documento.

Capisco che traducendo gli id ​​come questo, sto rompendo alcune convenzioni puriste di REST, ma penso che sia ragionevole date le circostanze. Sarei interessato a qualsiasi approccio alternativo che qualcuno si avvicini.

+0

Grazie per questo Matt. Quindi stai restituendo un ID intero da GET:/api/users? – Chris

+0

No, ho trovato troppo maldestro manipolare il set di risultati, quindi restituisco solo l'ID della stringa completa. L'app client mantiene l'id completo della stringa, ma quando crea un url con un id, rimuove la parte frontale usando qualcosa come id.split ("/") [1] –

0

Ho avuto questo problema quando ho provato Durandal JS con RavenDB.

La mia soluzione era di cambiare leggermente l'URL per farlo funzionare. Quindi nel tuo esempio:

GET /api/users/users/1 

E'

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

Da jQuery, questo diventa:

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

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