Come posso ottenere un oggetto HttpContext da HttpContextBase in ASP.NET MVC 1?


155

Sto lavorando con alcuni strumenti WebForms / MVC-agnostici e ho bisogno di ottenere un'istanza per HttpContextdare un riferimento a un HttpContextBaseoggetto. Non posso usarlo HttpContext.Currentperché ho bisogno che funzioni anche in modo asincrono ( HttpContext.Currentritorna nulldurante una richiesta asincrona). Sono consapevole HttpContextWrapper, ma va nella direzione sbagliata.

Risposte:


250

Il modo più semplice è ottenere l'applicazione ApplicationInstancee usare la sua Contextproprietà:

// httpContextBase is of type HttpContextBase
HttpContext context = httpContextBase.ApplicationInstance.Context;

(grazie a Ishmael Smyrnow che lo ha notato nei commenti)

Risposta originale:

Puoi, specialmente se l' HttpContextBaseistanza che ti è stata consegnata è di tipo HttpContextWrapperin fase di esecuzione. L'esempio seguente mostra come è possibile farlo. Suppone che tu abbia un metodo chiamato Fooche accetta il contesto come HttpContextBasema che quindi deve chiamare un metodo in un assembly di terze parti (che potresti non avere la fortuna di modificare) che si aspetta che il contesto venga digitato come HttpContext.

void Foo(HttpContextBase context) 
{
    var app = (HttpApplication) context.GetService(typeof(HttpApplication));
    ThirdParty.Bar.Baz(app.Context);
}

// Somewhere in assembly and namespace ThirdParty,
// in a class called Bar, there is Baz expecting HttpContext:

static void Baz(HttpContext context) { /* ... */ }

HttpContextBaseha un metodo chiamato GetServicecome risultato del supporto IServiceProvider. L' GetServiceoverride dei HttpContextWrapperdelegati GetServiceall'implementazione HttpContextdell'istanza di wrapping . L' GetServiceimplementazione di HttpContextpermette di query per i soliti sospetti come HttpApplication, HttpRequest, HttpResponsee così via. Accade solo che HttpApplicationabbia una proprietà chiamata Context e che restituisca un'istanza di HttpContext. Così si arriva alla avvolto HttpContextesempio chiedendo HttpContextBaseper HttpApplicationvia GetServiceseguita dalla lettura della Contextproprietà del restituita HttpApplicationistanza.

Diversamente HttpContextBase, GetServicenon appare come un membro pubblico HttpContextma ciò è dovuto al fatto che HttpContextimplementa IServiceProvider.GetServiceesplicitamente mentre HttpContextBasenon lo fa.

Tieni presente che Foonon è più testabile perché si basa sulla capacità di scartare il sottostante HttpContextdurante il test e che è quasi impossibile da falsificare / stub in primo luogo. Il punto di questa risposta, tuttavia, è di rispondere alla domanda "Come posso ottenere un oggetto HttpContext da HttpContextBase?", Letteralmente . La tecnica illustrata è utile in quelle situazioni in cui ti trovi inserito tra componenti che non hai necessariamente il lusso di modificare.


3
Risposta molto interessante, l'ho usata da sola in MVC per passare HttpContext da un filtro errori a ELMAH per la registrazione.
Chris Marisic,

1
bella risposta, scommetto che ci è voluto un po 'di scavo? :)
longhairedsi

Bella risposta! L'ho utilizzato soprattutto nel mio controller Elmah-MVC github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/…
Alexander Beletsky

36
Con un HttpContextBase, non puoi chiamare context.ApplicationInstance.Context?
Ishmael Smyrnow,

@IshmaelSmyrnow Accidenti, non come mi sono perso tra tutte le Http*Basevarianti restituite HttpContextBase. : P Aggiornerò la risposta.
Atif Aziz,

32

Puoi,

var abstractContext = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);

16
-1 questo è il modo sbagliato, questo ti dà la Base quando hai il Contesto, non viceversa.
Chris Marisic,

14

Non puoi.

Lo scopo di HttpContextBaseè quello di sottrarre la dipendenza dalla HttpContextclasse concreta . Sebbene possa contenere un concreto HttpContext (come nel caso di httpContextWrapper) , altre implementazioni potrebbero non avere assolutamente nulla a che fare HttpContext.

La tua migliore opzione è quella di definire una Fabbrica astratta personalizzata che può ottenere una HttpContextBaseper te, poiché puoi sempre avvolgere un calcestruzzo HttpContextin una HttpContextWrapper.


13
A proposito, questo è stato fatto orribilmente - ho capito che volevo avere una configurazione per i test unitari e capisco i livelli di astrazione - ma cosa dovresti fare quando vuoi usare le classi ASP.NET esistenti che si aspettano un HttpContext? (come msdn.microsoft.com/en-us/library/… )
marq

Sì, per testare le IHttpHandlerimplementazioni alla fine devi inserire un gran numero di astrazioni in (wrapper di risposta) solo per i tuoi test unitari, il che non sembra corretto ma finisce per essere l'unica opzione.
Chris S
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.