2009-07-22 11 views
13

Sto costruendo un'applicazione che segue in modo approssimativo il modello di repository con un livello di servizio in primo piano, simile alle prime versioni di MVC Storefront di Conery.Il livello di servizio può accedere a HttpContext?

Devo implementare una pagina che restituisca tutti gli utenti tranne l'utente corrente. Dispongo già di metodi GetUsers() sul repository e sui livelli del servizio, quindi la domanda è dove applicare "eccetto per l'utente corrente".

Il livello di servizio deve conoscere HttpContext, quindi applicare questa regola? Sono tentato di passare solo l'utente corrente (id) dal controller a questo metodo di servizio, ma sembra più pulito se il livello di servizio fosse HttpContext-aware e potesse farlo da solo.

Una ovvia alternativa è quella di applicare questa regola direttamente all'interno del controller, ma io non sono solo caldo su questa idea ...


Edit - solo per commentare le risposte: vedo i problemi con il problema della dipendenza inversa, qualcosa che stavo trascurando completamente. Segnalo come risposta a Mehrdad, ma tutti hanno davvero fornito una valida risposta che vale la pena di leggere!

risposta

18

Assolutamente no. La mia mentalità nel progettare questo tipo di cose è la seguente: presumo di dover scrivere un'app per Windows insieme all'applicazione Web e cercare di ridurre al minimo la dipendenza da elementi specifici del Web. Passare direttamente a HttpContext aumenterà l'accoppiamento del livello di servizio al livello dell'interfaccia utente Web che non è l'ideale.

4

È necessario non creare una dipendenza inversa tra il livello di servizio e il livello Web. Considerare cosa succede quando si desidera estendere il livello di servizio affinché funzioni con un'applicazione basata su moduli o un servizio Windows. Ora devi lavorare attorno alla dipendenza dal web per far funzionare i tuoi stessi metodi o duplicare un codice (forse, piccolo, ma ancora duplicato). Sarebbe meglio servire per estrarre l'identificatore dell'utente in qualcosa di utile nel contesto del livello di servizio e utilizzare quel valore con il livello di servizio. Anche la gestione del filtro sul sito Web è accettabile, ma se lo si fa più di una volta dovrebbe essere rifatto in un luogo comune e il livello di servizio è il punto naturale per farlo.

2

Ritengo utile creare una classe AppContext personalizzata che contenga il mio oggetto utente corrente (oltre ad altri dati contestuali). Questa classe non ha riferimenti a System.Web. Qualsiasi metodo di servizio che deve essere consapevole del contesto dovrebbe avere un parametro AppContext (ad esempio per controllare i diritti di sicurezza o ottenere l'utente corrente come nel tuo caso). Compila questo oggetto nel livello web e mantienilo in sessione se necessario. In questo modo il tuo livello di servizio non sa nulla di System.Web.

+0

Cosa c'è che non va con il semplice passaggio ID utente? –

+0

Niente di male, mi piace solo trattare tutte le situazioni sensibili al contesto allo stesso modo. – JonoW

+0

Mi piace questa idea, JonoW! Potrei semplicemente passare l'id per ora, se/quando i miei metodi di servizio cominceranno a diventare brutti con param e sovraccarichi, sarebbe fantastico. Potrei persino passare AppContext durante l'istanziazione dell'oggetto servizio, soddisfacendo in tal modo il mio desiderio di avere il servizio un po '"consapevole" ma non dipendente da System.Web. –

9

La risposta è, no.

Non solo il livello di servizio non deve dipendere dal livello di presentazione corrente, a mio avviso non dovrebbe dipendere dall'applicazione corrente. Ad esempio, non utilizzerei una classe personalizzata AppContext come JonoW suggerita here.

Invece, passare l'utente corrente come parametro al metodo GetAllUsersExceptForTheCurrentUser. In questo modo, il servizio può essere utilizzato da qualsiasi applicazione che deve elaborare gli utenti, non solo l'applicazione corrente.

+0

concordato. Nello specifico, ti ringrazierai di non aver aggiunto * context * e * state * a un livello di servizio nel momento in cui hai bisogno di metterlo dietro un load balancer. –

+0

Grazie, John, questo è un grande punto. Rende il mio riconsiderare la mia reazione iniziale al suggerimento di JonoW. –

+0

Ricevo quello che dici, ma quando dico che un metodo di servizio deve essere consapevole del contesto, intendo un metodo di servizio che deve sapere chi lo sta chiamando. Ad esempio, come gestite l'autorizzazione? cioè, se il chiamante del metodo è autorizzato a chiamare il metodo? Sono un po 'nuovo in questa arena, sono così felice di sapere come fanno gli altri/quali sono le migliori pratiche. Cheers – JonoW

1

No. In questo modo il codice sarà più difficile da testare e riutilizzare.

Tendo a creare un'interfaccia infrastruttura per questo tipo di cose (chiamarla IAuthentication o qualcosa del genere) ed esporre una proprietà CurrentUser su di essa. Poi l'avrei iniettato nel mio servizio tramite un costruttore. ovvero MyService pubblico (autenticazione IAuthentication)

Infine, è possibile creare un'implementazione consapevole di HttpContext di IAuthentication (ad esempio WebAuthentication).

Ora, quando si crea il servizio si crea le sue dipendenze oltre:

var myService = new MyService(new WebAuthentication()); 
var otherUsers = myService.GetAllOtherUsers(); 

Se si utilizza un contenitore CIO il brutto dipendenza può anche andare via!

Problemi correlati