Як отримати об’єкт HttpContext від HttpContextBase в ASP.NET MVC 1?


155

Я працюю з деякими інструментами WebForms / MVC-агностики, і мені потрібно отримати екземпляр HttpContextданої посилання на HttpContextBaseоб'єкт. Я не можу використовувати, HttpContext.Currentоскільки мені це потрібно для асинхронної роботи ( HttpContext.Currentповертається nullпід час асинхронного запиту). Я знаю HttpContextWrapper, але йде неправильним шляхом.

Відповіді:


250

Найпростіший спосіб - отримати додаток ApplicationInstanceта використовувати його Contextвластивість:

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

(спасибі Ізмаїлу Смирнову, який зазначив це у коментарях)

Оригінальна відповідь:

Ви можете, особливо якщо HttpContextBaseекземпляр, який вам передали, має тип HttpContextWrapperпід час виконання. Наступний приклад ілюструє, як ви можете це зробити. Він передбачає, що у вас є метод, який називається, Fooякий приймає контекст як, HttpContextBaseале потім повинен викликати метод у сторонній збірці (щоб ви не мали щастя змінити), який очікує, що контекст буде введено як 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) { /* ... */ }

HttpContextBaseмає метод, названий GetServiceв результаті підтримки IServiceProvider. GetServiceПеревизначення HttpContextWrapperделегатів до GetServiceреалізації обернутого HttpContextпримірника. GetServiceРеалізація HttpContextдозволяє запитувати для звичайних підозрюваних , як HttpApplication, HttpRequest, HttpResponseі так далі. Так буває, що HttpApplicationє властивість під назвою Context і яка повертає екземпляр HttpContext. Так один отримує в оберненої HttpContextінстанції з проханням HttpContextBaseза HttpApplicationдопомогою з GetServiceподальшим читанням Contextвластивості повертається HttpApplicationпримірника.

На відміну від цього HttpContextBase, GetServiceвін не є публічним членом, HttpContextале це тому, що HttpContextреалізує IServiceProvider.GetServiceexplicity, поки HttpContextBaseцього не робить.

Майте на увазі, що Fooце більше не перевіряється, оскільки він покладається на те, що зможете розгортати основу HttpContextпід час тестування, і це, поряд з неможливим підробляти / заглушувати в першу чергу. Суть цієї відповіді, однак, полягає у вирішенні питання "Як отримати об'єкт HttpContext з HttpContextBase?", Буквально . Проілюстрована методика корисна в тих ситуаціях, коли ви опинилися затиснутими між компонентами, не обов'язково повинні змінювати розкіш.


3
Дуже цікава відповідь, я просто використовував його в MVC, щоб передати HttpContext з фільтра помилок до ELMAH для ведення журналу.
Кріс Марісіч

1
приємна відповідь, ставка, що зайняло трохи копання? :)
longhairedsi

чудова відповідь! Це я використав, особливо в моєму контролері Elmah до MVC github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/…
Олександр Белецький,

36
З HttpContextBase ви не могли зателефонувати context.ApplicationInstance.Context?
Ізмаїл Смирнов

@IshmaelSmyrnow Дарт, це не так, як я пропустив це серед усіх Http*Baseваріантів, повернених HttpContextBase. : P Я оновлю відповідь.
Atif Aziz

32

Ти можеш,

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

16
-1 це неправильний шлях, це дає вам Базу, коли у вас є Контекст, а не навпаки.
Кріс Марісіч

14

Ви не можете.

Вся мета HttpContextBase- абстрагувати залежність від конкретного HttpContextкласу. Хоча він може містити конкретні HttpContext (як це відбувається httpContextWrapper) , інші реалізації можуть не мати абсолютно нічого спільного HttpContext.

Ваш найкращий варіант - визначити власну Анотаційну фабрику, яка може отримати HttpContextBaseдля вас, оскільки ви завжди можете обернути бетон HttpContextу HttpContextWrapper.


13
Це, до речі, було жахливо зроблено - я розумію, що хотів би встановити налаштування для одиничних тестів, і я розумію шари абстракції - але що WTH ви повинні робити, коли ви хочете використовувати існуючі класи ASP.NET, які очікують HttpContext? (наприклад, msdn.microsoft.com/en-us/library/… )
1111

Якщо ви хочете перевірити IHttpHandlerреалізацію, вам доведеться вводити ряд абстракцій у (обгортки відповідей) лише для ваших тестових одиниць.
Chris S
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.