HttpModule ATL Server Service InputStream Failure

1

I'm trying to add some SOAP message logging capabilities to an old, old ATL Server web service that is running in integrated mode in IIS 7.5 on a Windows Server 2008 box, but running into a strange problem. For further background, I've added the assembly that contains the HttpModule to the modules element of the web.config for the ATL Server web service.

I've been following the answer provided here and the logging itself works great.

However, whenever I use this logging capability, the service responds with "SOAP Invalid Request", while the log file has the SOAP message as expected. I've done lots of fiddling around with it and figured out that this only happens if/when I access the request object's InputStream property in my handler for the BeginRequest event. It will fail if I even simply set a variable to the length of the InputStream like this:

private void OnBegin(object sender, EventArgs e)
   {
   var request = _application.Request;
   //this will blow up
   var foo = request.InputStream.Position;
   }

If I don't touch the InputStream in my handler (which doesn't do much good when I'm only doing this to log the contents of the request, obviously), the request goes through perfectly.

I can access header values in the Request object and various other properties of the HttpApplication involved, but accessing the InputStream causes the service to choke.

Is there something intrinsic with ATL Server that will prevent me from doing this logging? Do I need to add some sort of locking or other safeguard in my BeginRequest handler to make sure this behaves? Is my handler hosing up the InputStream somehow causing it to be unusable for the service?

Another way of approaching this is to ask if there is a way to see the request as it gets to my service (i.e. after this HttpModule executes)?

It may also be worth noting that I am using SoapUI to test the service.

EDIT: I've now done some failed request tracing in IIS and I get this error message:

ModuleName IsapiModule 
Notification 128 
HttpStatus 500 
HttpReason Internal Server Error 
HttpSubStatus 0 
ErrorCode 0 
ConfigExceptionInfo  
Notification EXECUTE_REQUEST_HANDLER 
ErrorCode The operation completed successfully. (0x0) 

This comes in the handler for the ATL Server web service (i.e. the DLL for the service). Directly before that is the "GENERAL_READ_ENTITY_START" and "GENERAL_READ_ENTITY_END" messages, and the "END" has this message:

BytesReceived 0 
ErrorCode 2147942438 
ErrorCode Reached the end of the file. (0x80070026) 

Does that mean what I think it means? That the handler isn't getting any data? Is this more evidence pointing towards my HttpModule messing with the Request's InputStream?

c#
asp.net
soap
atl
httpmodule
asked on Stack Overflow May 17, 2012 by Sven Grosen • edited May 23, 2017 by Community

2 Answers

0

Are you sure your request object is valid? You're doing things slightly differently here from the sample you reference. They are extracting the stream from the sender argument whereas you obviously rely on a member variable.

0

So I finally determined that this wasn't a workable approach: I couldn't get the HttpModule to fire at all in IIS 6 (which I would need to have it to do for it to be an acceptable solution). I tried setting the Filter property on the Request object and all sorts of other crazy ideas, but none that led me to be able to both record the request body in the HttpModule and have the service still work.

So I did more digging and came upon this article on codeproject that talks about the inner workings of ATL Server, specifically the HandleRequest method in atlsoap.h. I mucked around in there for a while and figured out a way to get at the request body in there, and it was pretty simple to write it to a file manually from there.

For those curious, this is the final code I added to HandleRequest():

//****************************************REQUEST LOGGING**********************************************************
        BYTE* bytes = pRequestInfo->pServerContext->GetAvailableData();
        FILE* pFile;
        pFile = fopen("C:\\IISLog\\ATL.txt", "a");
        fwrite(bytes, 1, pRequestInfo->pServerContext->GetAvailableBytes(), pFile);
        fclose(pFile);
//****************************************REQUEST LOGGING********************************************************** 

I am going to still play around with it a bit more, but I have what appears to be a workable solution.

answered on Stack Overflow May 18, 2012 by Sven Grosen

User contributions licensed under CC BY-SA 3.0