R – .NET SOAP Extension is throwing NullReferenceException inside MethodInfo

.netexceptionsoap-extensionweb-services

NOTE: Using .NET 2.0, and VS2005 as IDE

Hello all,

I'm working on logging webservice calls to our database, and finally got the SoapExtension configured and running using a very stripped-down implementation that was ported over from another project. I've set it up in the configuration file so it will run for all methods. When I call my webservice, and the soap extension fires, a NullPointerException is thrown when the SoapServerMessage attempts to call its MethodInfo property:

System.Web.Services.Protocols.SoapException: There was an exception running the extensions specified in the config file. 
---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.Services.Protocols.SoapServerProtocol.get_MethodInfo()
at System.Web.Services.Protocols.SoapServerMessage.get_MethodInfo()
at MyService.SOAPLoggingExtension.LogInput(SoapMessage message)
at MyService.SOAPLoggingExtension.ProcessMessage(SoapMessage message) 
at System.Web.Services.Protocols.SoapMessage.RunExtensions(SoapExtension[] extensions, Boolean throwOnException)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)

The LogInput method is called during the BeforeDeserialize stage of ProcessMessage(SoapMessage):

SoapMessageStage.BeforeDeserialize:
   CopyStream(_oldStream, _newStream);
   _newStream.Position = 0;

   if(_enabled)
      LogInput(message);
   break;

And the LogInput method is failing when attempting to access the MethodInfo property of the message object it is trying to log. Here is the block of code where the property is called:

entry = new MyServerLogEntry();
entry.ServerURL = message.Url;
entry.Method = (message.MethodInfo == null) ? null : message.MethodInfo.Name;

When message.MethodInfo is called, it bubbles over to SoapServerProtocol.get_MethodInfo(), and the null reference exception gets thrown in there. I've googled, and checked around here on Stack Overflow, but haven't been able to find out why the MethodInfo property would be throwing an exception.

Does anyone know how to ensure this MethodInfo property is properly initialized during the web service call?

ADDITIONAL DETAILS: If I do not attempt to access the MethodInfo property, the extension works correctly and logs to my database.

Best Solution

After some trial and error, I have been able to solve this issue. While I do not entirely understand why, the SoapMessage object is not completely initialized at the BeforeDeserialize stage. Both the Action and MethodInfo properties throw errors at this stage.

However, during the AfterSerialize stage, these objects seem to be properly initialized. By moving the line which reads the message name to a later stage, the log entry object can be properly filled without throwing an exception.

It appears the correct order is:

  1. BeforeDeserialize

    a. Read Server URL

    b. Retrieve request information (certificates, user host address, etc.)

    c. Read request contents from stream

  2. AfterSerialize

    a. Read Exceptions

    b. Read MethodInfo information (and Action information if necessary)

    c. Read response contents from stream

Related Question