Асинхронный HttpWebRequests и пустой объект HttpContext.Current.Response / Request - PullRequest
5 голосов
/ 21 декабря 2009

У меня есть веб-приложение, которое сильно зависит от веб-сервисов. Все с сервисами делается асинхронно и с AddOnPreRequestHandlerExecuteAsync. Во всяком случае, большинство моих вызовов работают просто отлично, но некоторые возвращаются из своих асинхронных вызовов службы, чтобы найти нулевой объект HttpContext.Current.Response / Request в endprerequest, что, конечно, приводит к ошибкам в тот момент, когда я пытаюсь использовать любой из них. Оба объекта (Response и Request доступны / не равны NULL в начале запроса на сбой вызовов и работают в конце запроса других вызовов).

Кто-нибудь сталкивался с подобным или догадался, в чем может быть проблема?

Обновление. Похоже, что было найдено решение, если я создам переменную для HttpApplication на Init (из HttpModule, в котором все это происходит), доступ к HttpContext можно получить из этой переменной.

Обновление: та же проблема возникает при передаче HttpApplication или HttpContext.Current в функцию begin. Когда они передаются как часть «State» асинхронного вызова, они заканчиваются нулем в функции end, даже если они действительны в функции begin.

Обновление: я добавил некоторые записи в журналы и обнаружил, что асинхронный вызов, который я делаю, возвращается правильно, результаты есть, функция обратного вызова вызывается правильно.

Ответы [ 2 ]

5 голосов
/ 27 декабря 2009

Я подозреваю, что знаю проблему, с которой вы столкнулись. Ответ почти наверняка состоит в том, чтобы заменить использование HttpWebRequest на WebClient и использовать * Async методы WebClient.

Вот длинное объяснение: есть две совершенно разные модели асинхронного программирования: Асинхронный шаблон IAsyncResult и Асинхронный шаблон на основе событий . Шаблон IAsyncResult использует методы BeginXXX и EndXXX, использует экземпляры IAsyncResult, использует делегаты для обратных вызовов и поддерживает ожидание завершения. Шаблон на основе событий использует методы XXXAsync для инициирования асинхронных действий, использует события XXXCompleted вместо обратных вызовов для обработки завершения и (это важно для вашего случая) передает специфический для потока контекст в каждый обработчик события обратного вызова.

Другими словами, если вы поместите свой код обратного вызова в обработчик событий XXXCompleted (например, WebClient.DownloadStringCompleted), то HttpContext.Current будет заполнен правильно.

Если, однако, вы используете метод BeginXXX (например, HttpWebRequest.BeginGetResponse) и обратный вызов делегата, ваш обратный вызов будет выполнен в контексте потока, который не гарантирует наличие правильного ASP. NET контекст прилагается.

Как правило, классы библиотек .NET Framework используют либо один асинхронный шаблон, либо другой. Как правило, классы более низкого уровня (например, HttpWebRequest) будут использовать шаблон IAsyncResult, в то время как классы более высокого уровня (например, WebClient) будут использовать шаблон, основанный на событиях. Некоторые странные классы (например, автоматически сгенерированные прокси .NET Remoting) будут поддерживать оба шаблона, но это редкость.

Так что, если это легко сделать, я бы предложил перейти к WebClient и обработчикам событий вместо делегатов HttpWebRequest и callback. Это должно решить вашу проблему. Если переключиться на WebClient слишком сложно, прокомментируйте, и я, вероятно, могу предложить несколько более неясных альтернатив.

0 голосов
/ 05 января 2010

Кажется, что нашел решение, если я создаю переменную для HttpApplication на Init (из HttpModule, в котором все это происходит), HttpContext может быть доступен из этой переменной.

...