CHttpModule::OnAsyncCompletion (Método)
Representa el método que controlará un evento de finalización asincrónica, que se produce después de que una operación asincrónica haya terminado de procesarse.
Sintaxis
virtual REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(
IN IHttpContext* pHttpContext,
IN DWORD dwNotification,
IN BOOL fPostNotification,
IN OUT IHttpEventProvider* pProvider,
IN IHttpCompletionInfo* pCompletionInfo
);
Parámetros
pHttpContext
[IN] Puntero a una interfaz IHttpContext .
dwNotification
[IN] Valor DWORD
que contiene la máscara de bits de la notificación relacionada.
fPostNotification
[IN] true
para indicar que la notificación es para un evento posterior; de lo contrario, false
.
pProvider
[IN] Puntero a una interfaz IHttpEventProvider .
pCompletionInfo
[IN] Puntero a una interfaz IHttpCompletionInfo .
Valor devuelto
Valor de REQUEST_NOTIFICATION_STATUS .
Comentarios
A diferencia de muchos de los otros métodos de CHttpModule a los que se llama mediante el registro para notificaciones específicas, IIS llamará al método de OnAsyncCompletion
un módulo solo cuando haya finalizado una operación asincrónica. Por ejemplo, cuando un módulo de nivel de solicitud llama al método IHttpResponse::WriteEntityChunks y especifica la finalización asincrónica, IIS llamará al método del OnAsyncCompletion
módulo cuando se complete la operación.
Cuando IIS llama al OnAsyncCompletion
método , especificará el tipo de notificación en el dwNotification
parámetro y indicará si la notificación era para un evento o posterior mediante el fPostNotification
parámetro . IIS también proporciona una IHttpCompletionInfo
interfaz a la que apunta el pCompletionInfo
parámetro . Puede usar esta interfaz para recuperar información adicional sobre la finalización asincrónica.
Ejemplo
En el ejemplo de código siguiente se muestra cómo crear un módulo HTTP que realice las tareas siguientes:
El módulo se registra para las notificaciones de RQ_BEGIN_REQUEST y RQ_MAP_REQUEST_HANDLER .
El módulo crea una
CHttpModule
clase que contiene los métodos OnBeginRequest, OnMapRequestHandler yOnAsyncCompletion
.Cuando un cliente web solicita una dirección URL, IIS llama al método del
OnBeginRequest
módulo. Este método realiza las tareas siguientes:Borra el búfer de respuesta existente y establece el tipo MIME de la respuesta.
Crea una cadena de ejemplo y la devuelve al cliente web de forma asincrónica.
Comprueba si hay un error o finalización asincrónica. Si la finalización asincrónica está pendiente, el módulo devuelve un estado de notificación pendiente a la canalización de procesamiento de solicitudes integrada.
IIS llama al método del
OnMapRequestHandler
módulo. Este método realiza las tareas siguientes:Vacía el búfer de respuesta actual en el cliente web.
Comprueba si hay un error o finalización asincrónica. Si la finalización asincrónica está pendiente, el módulo devuelve un estado de notificación pendiente a la canalización.
Si se requiere finalización asincrónica, IIS llama al método del
OnAsyncCompletion
módulo. Este método realiza las tareas siguientes:Comprueba si hay una interfaz válida
IHttpCompletionInfo
. Si se pasó una interfaz válidaIHttpCompletionInfo
, el método llama a los métodos GetCompletionBytes y GetCompletionStatus , respectivamente, para recuperar los bytes completados y devolver el estado de la operación asincrónica.Crea cadenas que contienen la información de finalización y escribe la información como un evento en el registro de la aplicación del Visor de eventos.
El módulo quita la
CHttpModule
clase de la memoria y, a continuación, se cierra.
#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <httpserv.h>
#include <wchar.h>
// Create the module class.
class MyHttpModule : public CHttpModule
{
public:
REQUEST_NOTIFICATION_STATUS
OnBeginRequest(
IN IHttpContext * pHttpContext,
IN IHttpEventProvider * pProvider
)
{
UNREFERENCED_PARAMETER( pProvider );
// Create an HRESULT to receive return values from methods.
HRESULT hr;
// Buffer to store the byte count.
DWORD cbSent = 0;
// Buffer to store if asyncronous completion is pending.
BOOL fCompletionExpected = false;
// Create an example string to return to the Web client.
char szBuffer[] = "Hello World!";
// Clear the existing response.
pHttpContext->GetResponse()->Clear();
// Set the MIME type to plain text.
pHttpContext->GetResponse()->SetHeader(
HttpHeaderContentType,"text/plain",
(USHORT)strlen("text/plain"),TRUE);
// Create a data chunk.
HTTP_DATA_CHUNK dataChunk;
// Set the chunk to a chunk in memory.
dataChunk.DataChunkType = HttpDataChunkFromMemory;
// Set the chunk to the buffer.
dataChunk.FromMemory.pBuffer =
(PVOID) szBuffer;
// Set the chunk size to the buffer size.
dataChunk.FromMemory.BufferLength =
(USHORT) strlen(szBuffer);
// Insert the data chunk into the response.
hr = pHttpContext->GetResponse()->WriteEntityChunks(
&dataChunk,1,TRUE,TRUE,&cbSent,&fCompletionExpected);
// Test for a failure.
if (FAILED(hr))
{
// Set the HTTP status.
pHttpContext->GetResponse()->SetStatus(
500,"Server Error",0,hr);
// End additional processing.
return RQ_NOTIFICATION_FINISH_REQUEST;
}
// Test for pending asynchronous operations.
if (fCompletionExpected)
{
return RQ_NOTIFICATION_PENDING;
}
// Return processing to the pipeline.
return RQ_NOTIFICATION_CONTINUE;
}
REQUEST_NOTIFICATION_STATUS
OnMapRequestHandler(
IN IHttpContext * pHttpContext,
IN IMapHandlerProvider * pProvider
)
{
// Create an HRESULT to receive return values from methods.
HRESULT hr;
// Buffer to store the byte count.
DWORD cbSent = 0;
// Buffer to store if asyncronous completion is pending.
BOOL fCompletionExpected = false;
// Flush the response to the client.
hr = pHttpContext->GetResponse()->Flush(
TRUE,FALSE,&cbSent,&fCompletionExpected);
// Test for a failure.
if (FAILED(hr))
{
// Set the HTTP status.
pHttpContext->GetResponse()->SetStatus(
500,"Server Error",0,hr);
}
// Test for pending asynchronous operations.
if (fCompletionExpected)
{
return RQ_NOTIFICATION_PENDING;
}
// End additional processing.
return RQ_NOTIFICATION_CONTINUE;
}
REQUEST_NOTIFICATION_STATUS
OnAsyncCompletion(
IN IHttpContext * pHttpContext,
IN DWORD dwNotification,
IN BOOL fPostNotification,
IN IHttpEventProvider * pProvider,
IN IHttpCompletionInfo * pCompletionInfo
)
{
if ( NULL != pCompletionInfo )
{
// Create strings for completion information.
char szNotification[256] = "";
char szBytes[256] = "";
char szStatus[256] = "";
// Retrieve and format the completion information.
sprintf_s(szNotification,255,"Notification: %u",
dwNotification);
sprintf_s(szBytes,255,"Completion Bytes: %u",
pCompletionInfo->GetCompletionBytes());
sprintf_s(szStatus,255,"Completion Status: 0x%08x",
pCompletionInfo->GetCompletionStatus());
// Create an array of strings.
LPCSTR szBuffer[3] = {szNotification,szBytes,szStatus};
// Write the strings to the Event Viewer.
WriteEventViewerLog(szBuffer,3);
}
// Return processing to the pipeline.
return RQ_NOTIFICATION_CONTINUE;
}
MyHttpModule(void)
{
// Open a handle to the Event Viewer.
m_hEventLog = RegisterEventSource( NULL,"IISADMIN" );
}
~MyHttpModule(void)
{
// Test if the handle for the Event Viewer is open.
if (NULL != m_hEventLog)
{
// Close the handle to the Event Viewer.
DeregisterEventSource( m_hEventLog );
m_hEventLog = NULL;
}
}
private:
// Handle for the Event Viewer.
HANDLE m_hEventLog;
// Define a method that writes to the Event Viewer.
BOOL WriteEventViewerLog(LPCSTR * lpStrings, WORD wNumStrings)
{
// Test whether the handle for the Event Viewer is open.
if (NULL != m_hEventLog)
{
// Write any strings to the Event Viewer and return.
return ReportEvent(
m_hEventLog, EVENTLOG_INFORMATION_TYPE,
0, 0, NULL, wNumStrings, 0, lpStrings, NULL );
}
return FALSE;
}
};
// Create the module's class factory.
class MyHttpModuleFactory : public IHttpModuleFactory
{
public:
HRESULT
GetHttpModule(
OUT CHttpModule ** ppModule,
IN IModuleAllocator * pAllocator
)
{
UNREFERENCED_PARAMETER( pAllocator );
// Create a new instance.
MyHttpModule * pModule = new MyHttpModule;
// Test for an error.
if (!pModule)
{
// Return an error if we cannot create the instance.
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
else
{
// Return a pointer to the module.
*ppModule = pModule;
pModule = NULL;
// Return a success status.
return S_OK;
}
}
void Terminate()
{
// Remove the class from memory.
delete this;
}
};
// Create the module's exported registration function.
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo * pModuleInfo,
IHttpServer * pGlobalInfo
)
{
UNREFERENCED_PARAMETER( dwServerVersion );
UNREFERENCED_PARAMETER( pGlobalInfo );
return pModuleInfo->SetRequestNotifications(
new MyHttpModuleFactory,
RQ_BEGIN_REQUEST | RQ_MAP_REQUEST_HANDLER,
0
);
}
El módulo debe exportar la función RegisterModule . Puede exportar esta función mediante la creación de un archivo de definición de módulo (.def) para el proyecto, o bien puede compilar el módulo mediante el /EXPORT:RegisterModule
modificador . Para obtener más información, vea Tutorial: Creación de un módulo HTTP de Request-Level mediante código nativo.
Opcionalmente, puede compilar el código mediante la __stdcall (/Gz)
convención de llamada en lugar de declarar explícitamente la convención de llamada para cada función.
Requisitos
Tipo | Descripción |
---|---|
Remoto | - IIS 7.0 en Windows Vista - IIS 7.5 en Windows 7 - IIS 8.0 en Windows 8 - IIS 10.0 en Windows 10 |
Servidor | - IIS 7.0 en Windows Server 2008 - IIS 7.5 en Windows Server 2008 R2 - IIS 8.0 en Windows Server 2012 - IIS 8.5 en Windows Server 2012 R2 - IIS 10.0 en Windows Server 2016 |
Producto | - IIS 7.0, IIS 7.5, IIS 8.0, IIS 8.5, IIS 10.0 - IIS Express 7.5, IIS Express 8.0, IIS Express 10.0 |
Encabezado | Httpserv.h |