1

我有一个 SoapExtension。它记录了我所有的网络服务请求和响应。我认为项目中有超过一千个 Web 服务调用。我的问题是,如果我的 web 服务调用以超时或 httpexceptions(如 403、404)结束,我将无法记录请求。我也需要记录这些异常。

这是我的 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();
    }

}
4

1 回答 1

-2

以下文字可能会帮助您解决问题。

“SoapExtension 解决方案

解决这个问题的最流行的方法(到目前为止我发现)是编写一个自定义的 SoapExtension 子类,它允许您在 Web 服务请求和响应的不同阶段对 SoapMessage 进行低级访问。当发生未处理的异常时,可以在响应 SoapMessage 中捕获 SoapException(通过 Exception 属性)。SoapException 的 InnerException 属性然后包含实际未处理的异常。此时,您可以在异常发生时记录异常,因此当您从技术支持部门收到该电子邮件时,您就可以继续做一些事情了。

但是,如果您曾经开发过真正的面向公众的 Web 服务(就像我们的一样),您很快就会同意仅仅记录异常是不够的。通常,您希望对发送回调用者的 SoapException 本身的内容进行更多控制。SoapExtension 子类方法使您能够修改 SoapException,但级别非常低。具体来说,它已经被反序列化为其代表性的 SOAP 故障 XML,您必须进行一些花哨的流操作才能将任何自定义内容插入到该故障中(例如:添加详细信息元素)。在我看来,这是一个 hack,而不是一个非常优雅的解决方案。相反,我们应该在抛出 SoapException 之前对其进行更多控制。理想情况下,如果我们可以自己创建并抛出 SoapException,我们可以对产生的 SOAP 错误的内容(如错误代码和详细信息)有更多的控制。这样我们就不必费心拦截和操纵原始 SOAP 消息本身了。”

请访问链接了解更多信息: http ://beyondthispoint.blogspot.co.uk/2008/04/managing-unhandled-exceptions-in-aspnet.html

于 2013-03-05T14:35:52.960 回答