2009-12-21 6 views
5

Tengo una aplicación web que depende en gran medida de los servicios web. Todo con los servicios se realiza de forma asíncrona y con AddOnPreRequestHandlerExecuteAsync. De todos modos, la mayoría de mis llamadas funcionan bien, pero algunas vuelven de sus llamadas de servicio asíncronas para encontrar un objeto nulo HttpContext.Current.Response/Request en la solicitud final, que por supuesto errores en el instante que trato de usar cualquiera. Ambos objetos (Respuesta y Solicitud están disponibles/no son nulos en el comienzo de la solicitud de llamadas defectuosas y funcionan al final de la solicitud de otras llamadas).HttpWebRequests asincrónico y un objeto nulo HttpContext.Current.Response/Request

¿Alguien se encuentra con algo similar, o tiene una conjetura sobre cuál podría ser el problema?

Actualización: Parece que he encontrado una solución, si creo una variable para HttpApplication en Init (del HttpModule esto ocurre), se puede acceder al HttpContext desde esa variable.

Actualización: Al pasar HttpApplication o HttpContext.Current en la función begin tiene el mismo problema. Cuando pasan como parte del "Estado" de la llamada asincrónica, terminan nulos en la función final, aunque son válidos en la función de inicio.

Actualización: He agregado algunos registros y encontré que la llamada asincrónica que estoy realizando está regresando correctamente, los resultados están ahí, la función de devolución de llamada se invoca correctamente.

Respuesta

0

Parece haber encontrado una solución, si creo una variable para HttpApplication en Init (del HttpModule esto ocurre), se puede acceder al HttpContext desde esa variable.

+0

¿Puede describir con detalles cómo resolvió el problema? – omoto

+0

En mi HttpModule tengo una variable de tipo HttpApplication. En la llamada a la función init() configuro esta variable a HttpApplication que se pasa a init. En BeginPreRequestHandlerExecute y EndPreRequestHandlerExecute me refiero al HttpContext actual usando oApplication.Context, oApplication es el nombre de la variable HttpApplication en mi HttpModule. – aepheus

5

Sospecho que sé el problema que te estás encontrando. La respuesta, casi con certeza, es reemplazar el uso de HttpWebRequest con WebClient, y usar los métodos * Async de WebClient.

Aquí está la larga explicación: hay dos modelos de programación Async totalmente diferentes: el IAsyncResult Async Pattern y el Event-based Asynchronous Pattern. El patrón IAsyncResult usa los métodos BeginXXX y EndXXX, utiliza instancias IAsyncResult, usa delegados para devoluciones de llamadas y admite la espera de la finalización. El patrón basado en eventos usa los métodos XXXAsync para iniciar acciones asíncronas, usa eventos XXXCompleted en lugar de devoluciones para manejar la finalización, y (esto es importante para su caso) transfiere el contexto específico de subprocesos en cada controlador de eventos de devolución de llamada.

En otras palabras, si coloca su código de devolución de llamada dentro de un controlador de eventos XXXCompleted (como WebClient.DownloadStringCompleted), entonces HttpContext.Current se completará correctamente.

Si, sin embargo, utiliza un método BeginXXX (como HttpWebRequest.BeginGetResponse) y una devolución de llamada delegada, su devolución de llamada se ejecutará en el contexto de un hilo que no garantiza que tenga el contexto ASP.NET adecuado.

En general, las clases de la biblioteca .NET Framework utilizan un patrón asíncrono u otro. Normalmente, las clases de nivel inferior (por ejemplo, HttpWebRequest) utilizarán el patrón IAsyncResult, mientras que las clases de nivel superior (por ejemplo, WebClient) utilizarán el patrón basado en eventos. Algunas clases de bichos raros (por ejemplo, proxies de Remoting .NET autogenerados) admitirán ambos patrones, pero eso es una rareza.

Así que si es fácil de hacer, le sugiero que se mueva a WebClient y controladores de eventos en lugar de HttpWebRequest y delegados de devolución de llamada. Esto debería solucionar tu problema. Si cambiar a WebClient es demasiado difícil, comente y probablemente pueda sugerir algunas alternativas más oscuras.

+0

No estoy seguro de lo fácil que esto sería implementar en mi caso.Creo que estoy vinculado al patrón IAsyncResult al menos en el nivel base porque ese es el patrón que admite AddOnPreRequestHandlerExecuteAsync. Y, dado que actualmente tengo cosas que funcionan simplemente guardando el estado en una variable, preferiría no meterme con eso. – aepheus

Cuestiones relacionadas