Thursday, October 2, 2014

ASP.Net Web Service Debugging Tip

Intro

I'm a big fan of Web API in .Net, as they're simple to write and a good standard way to get things done. However we can't always get what we want, and there are many old-school web services still in place at work. I frequently have to troubleshoot these things to find root causes of errors, and proper logging is key in these situations. Having an exception log with a stack trace is a good first step, but I've found something I like just as much: Logging the complete request from the client.

Solution

If we start with a standard exception log, we can hopefully find the right chunk of code when a customer has an issue. We should have date/time, possibly the caller, the type of exception, and if we're lucky a full stack trace. Sometimes however we need more, as we don't know the data that was passed in which caused the service to 'splode. To that end, I've written and succesfully used a method that will read the full SOAP request so that you can log it somewhere. Here's the beast:

    private string GetRawSoapRequest()
    {
      string soapRequest = "";
      try
      {
        // Get raw request body
        if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Request.InputStream != null)
        {
          using (Stream receiveStream = HttpContext.Current.Request.InputStream)
          {
            // Move to begining of input stream and read
            receiveStream.Position = 0;
            using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
              soapRequest = readStream.ReadToEnd();
          }
        }
      }
      catch { /*eat it*/ }
      return soapRequest;
    }


It's quite simple. All we do is get a stream reference to the current request inputstream, read it into a string, and return the string. Note that if we throw any kind of exception in the method we just eat it. After all, we don't want to interrupt normal processing because we failed to retrieve some logging information.

How would one use this method in a web service? This is also simple, and here's an example:

    [WebMethod]
    public void AWebMethod(string someString)
    {
      try
      {
        DoSomething(someString);
      }
      catch (Exception ex)
      {
        LogException(ex, GetRawSoapRequest());
        throw;
      }
    }



Our sample WebMethod AWebMethod does a little bit of work and catches any exceptions that may be thrown. In the catch block we log the exception, calling our new GetRawSoapRequest method, and voila! We've now logged the exception and the full SOAP request. This makes tracking down web service exceptions much easier.

What's Next?

  • Security: Your service may accept personal or sensitive information. If so, be careful what you do with the raw request as you might end up storing data in an unencrypted format unintentionally.
  • Compression: Depending on how much stuff you're sending up to the web service, the raw SOAP request can get pretty large. You might want to compress this value before storing it.

No comments:

Post a Comment