Utilizzo della pipeline Web Api per standardizzare le strutture di ritorno

4

Ho avuto una discussione sulla standardizzazione delle strutture di ritorno in un'API e il modo migliore per applicarla ai nostri servizi. Il modo più rapido con cui abbiamo lavorato è stato quello di far sì che i nostri controller in .NET Web Api restituiscano la stessa classe di modelli, quindi abbiamo trovato qualcosa di simile

class ResponseObject<T> 
{
    public T Data {get;set;}
    public Permissions UserPermissions {get;set;}
    public Message ObjectMessage {get;set;}
    public Status ObjectStatus {get;set;}
}

E ogni controller restituisce questo strcuture e riempie le proprietà comuni. Abbiamo anche creato alcune funzioni di supporto in modo che i controller che condividevano lo stesso tipo di ritorno T non stessero riscrivendo le stesse cose più e più volte.

Questo funziona bene per la maggior parte, ma la mia idea è stata invece di fare in modo che ogni controller lo trasformasse in un filtro azione.

public class MyResponseHandler : ActionFilterAttribute
{
    public override OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var objectContext = actionExecutedContext.Response.Content as ObjectContent;
        if(objectContent != null)
        {
            var val = objectContent.Value;
            var type = objectContent.ObjectType;

            actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(actionExecutedContext.Response.StatusCode, 
                                                                                          new ResponseObject<type>(){data = val})
        }
    }
}

Per le altre proprietà nel comune ResponseObject la mia idea era che queste potevano essere gestite con più filtri di azione nella pipeline per riempirli. Ho pensato che fosse un buon approccio perché gli sviluppatori dovevano solo preoccuparsi di restituendo l'oggetto di cui si preoccupavano veramente per il controller e quindi la pipeline gestiva tutto allo stesso modo per ogni tipo di oggetto. Alla fine abbiamo ritenuto eccessivo e ci sono stati alcuni timori che il gasdotto avrebbe avuto troppa logica e le decisioni prese in esso portando a un sacco di errori difficili da debug. Ma sono curioso di vedere quali altre persone hanno pensato a questo approccio o se qualcuno ha fatto qualcosa di simile ad applicare le strutture di ritorno in un'API.

    
posta ThrowsException 08.04.2017 - 17:53
fonte

1 risposta

3

Come per tutte le cose di questa natura, la risposta è: dipende. Stai affrontando la cosa importante, che sta avendo un'API coerente (non c'è niente di peggio di un'API che è incoerente nel modo in cui la usi), ma il modo in cui implementerai ciò avrà ovviamente vantaggi e svantaggi. Quello che suggerisco è scegliere il percorso più sicuro e l'implementazione più controllabile.

Il fatto è questo: non puoi predire il futuro. Spostando questa implementazione alla pipeline, quello che stai facendo è prevedere che tutti i tuoi controller si adatteranno a un certo modo di lavorare. Tutti dovrebbero generare la stessa struttura di risposta, ma alcuni potrebbero avere delle particolarità nel modo in cui lo fanno (cosa succede se restituisci sempre la stessa cosa ma con autorizzazioni diverse? Come controllerai le autorizzazioni nella pipeline quando il tuo metodo restituisce solo i dati di risposta ?). Le astrazioni perdono e quando lo fanno le persone tendono a mantenere l'astrazione ma a modificarla per adattarsi ancora alle nuove situazioni.

Ho usato entrambi i metodi per farlo e tendo a preferire l'implementazione in cui si restituisce ResponseObject<T> invece di avere la struttura di risposta creata dalla pipeline. È più lavoro perché devi sempre scriverlo a mano. Ma è esplicito. Con i metodi di supporto corretti, diventa facile, anche in futuro, quando le cose che non vedi iniziano a succedere.

Con l'altra implementazione, quello che ho scoperto è che inizi a mettere varie parti della logica non correlata in questo livello e che diventa più difficile tracciare gli errori perché la risposta non è finita quando torni dal tuo metodo.

Come ho detto, tutto dipende dalla complessità della tua applicazione e dai casi d'uso. Se la tua app è semplice, puoi anche tenerla nella pipeline e fare in modo che l'implementazione rimanga solo un livello stupido. YMMV

    
risposta data 11.04.2017 - 12:41
fonte

Leggi altre domande sui tag