我正在尝试为我的ASP.NET webservice创建一个记录所有SOAP方法调用的日志服务。我已经查看了从控制台应用程序记录SOAP消息和MSDN上SOAP扩展的演示步骤(http://msdn.microsoft.com/en-us/library/s25h0swd%28v=vs.100%29.aspx),但它们似乎没有完全覆盖此问题。
我不想改变SOAP消息,只是将其记录到数据库表中。我正在尝试读取SOAP消息流,解析它作为XML,记录XML,然后让调用继续执行。但是当我读取流时,它就被释放/丢弃了。我尝试过复制流内容以避免打断流程。
根据演示步骤,
根据演练,我应该使用
我已经尝试将消息流复制到单独的流中并将其用于日志记录,还尝试设置某种状态以判断是否已经运行了
我仍然需要在
我不想改变SOAP消息,只是将其记录到数据库表中。我正在尝试读取SOAP消息流,解析它作为XML,记录XML,然后让调用继续执行。但是当我读取流时,它就被释放/丢弃了。我尝试过复制流内容以避免打断流程。
根据演示步骤,
ProcessMessage
方法应该类似于以下内容:public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
// Write the SOAP message out to a file.
WriteOutput( message );
break;
case SoapMessageStage.BeforeDeserialize:
// Write the SOAP message out to a file.
WriteInput( message );
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
在 BeforeDeserialize
阶段中,我成功地解析了流,但是在 AfterSerialize
阶段中再次调用 ProcessMessage
,此时流已被使用,并且不再包含任何数据。
根据 SOAP 扩展使用 SOAP 消息修改 (http://msdn.microsoft.com/en-us/library/esw638yk%28v=vs.100%29.aspx) 的说明,SOAP 调用经过以下步骤:
服务器端接收请求消息并准备响应
- Web 服务器上的 ASP.NET 接收 SOAP 消息。
- 在 Web 服务器上创建了 SOAP 扩展的新实例。
- 如果这是此 SOAP 扩展在服务器上第一次与此 Web 服务一起执行,则在服务器上运行的 SOAP 扩展上调用 GetInitializer 方法。
- 调用 Initialize 方法。
- 调用 ChainStream 方法。
- 使用 SoapMessageStage 设置为 BeforeDeserialize 调用 ProcessMessage 方法。
- ASP.NET 反序列化 XML 中的参数。
- 使用 SoapMessageStage 设置为 AfterDeserialize 调用 ProcessMessage 方法。
- ASP.NET 创建实现 Web 服务的类的新实例,并调用 Web 服务方法,将反序列化的参数传递给该方法。该对象驻留在与 Web 服务器相同的计算机上。
- Web 服务方法执行其代码,最终设置返回值和任何 out 参数。
- 使用 SoapMessageStage 设置为 BeforeSerialize. 调用 ProcessMessage 方法。
- Web 服务器上的 ASP.NET 将返回值和 out 参数序列化为 XML。
- 使用 SoapMessageStage 设置为 AfterSerialize 调用 ProcessMessage 方法。
- ASP.NET 将 SOAP 响应消息通过网络发送回 Web 服务客户端。
AfterSerialize
阶段再次调用ProcessMessage
,但这次流已经被使用完毕,当我尝试记录它时会抛出异常。根据演练,我应该使用
ChainStream
方法,并且应该在上面的第5步中运行。当我调用它时,它会运行两次,一次在BeforeDeserialize
之前,一次在AfterSerialize
之前。我已经尝试将消息流复制到单独的流中并将其用于日志记录,还尝试设置某种状态以判断是否已经运行了
BeforeDeserialize
,但问题仍然存在。我仍然需要在
AfterSerialize
中编写代码来处理发送回客户端的响应。但是,如果我尝试删除AfterSerialize
中的代码,只运行BeforeDeserialize
中的代码,我会得到一个`HTTP 400: Bad Request`。
所有这些操作都发生在实际方法调用之前,所以我甚至没有机会进入方法内部的代码(步骤10)。