How to handle Timeout exceptions in SoapExtension

2k Views Asked by At

I have a SoapExtension. It logs my all webservice requests and responses. I think there are over one thousand of webservice calls in project. My problem is i cant log request if my webservice call ends with timeout or httpexceptions like 403, 404 . I need to log these kind of exceptions too.

This is my SoapExtension

public class SoapLogger : SoapExtension
{
    Stream orgStream;
    Stream newStream;
    LogItem logItem;

    // When the SOAP extension is accessed for the first time, the XML Web
    // service method it is applied to is accessed to store the file
    // name passed in, using the corresponding SoapExtensionAttribute.    
    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return 0;
    }

    // The SOAP extension was configured to run using a configuration file
    // instead of an attribute applied to a specific XML Web service
    // method.
    public override object GetInitializer(Type WebServiceType)
    {
        return 0;
    }

    // Receive the file name stored by GetInitializer and store it in a
    // member variable for this specific instance.
    public override void Initialize(object initializer)
    {
        logItem = new LogItem();
    }

    // Save the Stream representing the SOAP request or SOAP response into
    // a local memory buffer.
    public override Stream ChainStream(Stream stream)
    {
        orgStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    //  If the SoapMessageStage is such that the SoapRequest or
    //  SoapResponse is still in the SOAP format to be sent or received,
    //  save it out to a file.
    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize:
                WriteOutput();
                break;
            case SoapMessageStage.BeforeDeserialize:
                WriteInput(message);
                break;
            case SoapMessageStage.AfterDeserialize:
                CheckException(message);
                break;
            default:
                throw new Exception("invalid soap stage");
        }
    }

    public void CheckException(SoapMessage message)
    {

        logItem.WebClassName = message.MethodInfo.DeclaringType.FullName;
        logItem.WebMethodName = message.MethodInfo.Name;

        MethodBase method = FindMethod(logItem.WebMethodName);

        logItem.MethodName = method != null ? method.Name : "";
        logItem.ClassName = method != null ? method.DeclaringType.Name : "";

        logItem.Exception = message.Exception != null ? message.Exception.Message : "";

        LogToDB(logItem);
    }

    MethodBase FindMethod(string webMethodName)
    {
        try
        {
            StackFrame[] stackFrames = new StackTrace().GetFrames();

            int i;
            for (i = 0; i < stackFrames.Length; i++)
            {
                if (stackFrames[i].GetMethod().Name == webMethodName) break;
            }
            return i < stackFrames.Length - 1 ? stackFrames[i + 1].GetMethod() : null;
        }
        catch
        {
            return null;
        }
    }

    void LogToDB(LogItem logItem)
    {
        // I am logging logItem to db
    }

    public void WriteOutput()
    {
        newStream.Position = 0;

        logItem.Request = CopyString(newStream);
        logItem.StartTime = DateTime.Now;

        newStream.Position = 0;
        Copy(newStream, orgStream);
        newStream.Position = 0;
    }

    public void WriteInput(SoapMessage message)
    {
        Copy(orgStream, newStream);
        newStream.Position = 0;

        logItem.Response = CopyString(newStream);
        logItem.EndTime = DateTime.Now;

        newStream.Position = 0;
    }

    void Copy(Stream from, Stream to)
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
    }

    string CopyString(Stream from)
    {
        TextReader reader = new StreamReader(from);
        return reader.ReadToEnd();
    }

}
1

There are 1 best solutions below

1
On

The following text might help you to solve your problem.

"The SoapExtension Solution

The most popular approach to solving this problem (that I've found so far) is to code up a custom SoapExtension subclass, which privodes you low-level access to the SoapMessage at different stages of the web service request and response. When the unhandled exception occurs, the SoapException can be captured in the response SoapMessage (via the Exception property). The SoapException's InnerException property then contains the actual unhandled exception. At this point you can at log the exception on its way out the door so when you get that email from your tech support department, you've got something to go on.

But if you've ever developed a real public-facing web service (like ours is), you'll quickly agree that simply logging the exception isn't enough. Often times you want a little more control over the contents of the SoapException itself that gets sent back to the caller. The SoapExtension subclass approach gives you the ability to modify the SoapException, but at a very low level. Specifically, it's already been deserialized into its representative SOAP fault XML and you have to do some fancy stream manipulation to insert any custom content into that fault (ex: add a detail element). In my opinion, this is a hack and not a very ellegant solution. Instead we should have more control of the SoapException before it gets thrown. Ideally if we could create and throw the SoapException ourselves, we could have much more control over the contents of the resuling SOAP fault (like the fault code and detail). Then we wouldn't have to bother with intercepting and manipulating the raw SOAP messages themselves."

Please visit the link for more information : http://beyondthispoint.blogspot.co.uk/2008/04/managing-unhandled-exceptions-in-aspnet.html