【发布时间】:2014-01-19 15:08:45
【问题描述】:
我正在尝试为对我的 ASP.NET Web 服务的所有 SOAP 方法调用创建一个日志记录服务。我一直在看 Log SOAP messages from a console application 和 MSDN 上的 SOAP 扩展演练 (http://msdn.microsoft.com/en-us/library/s25h0swd%28v=vs.100%29.aspx),但它们似乎并未完全涵盖它。
我不想更改 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 扩展的新实例。
- 在 Web 服务器上,如果这是第一次在服务器端使用此 Web 服务执行此 SOAP 扩展,则在服务器上运行的 SOAP 扩展上调用 GetInitializer 方法。
- Initialize 方法被调用。
- ChainStream 方法被调用。
- 调用 ProcessMessage 方法时将 SoapMessageStage 设置为 BeforeDeserialize。
- ASP.NET 反序列化 XML 中的参数。
- 调用 ProcessMessage 方法时将 SoapMessageStage 设置为 AfterDeserialize。
- ASP.NET 创建实现 Web 服务的类的新实例并调用 Web 服务方法,传入反序列化的参数。此对象与 Web 服务器位于同一台计算机上。
- Web 服务方法执行其代码,最终设置返回值和所有输出参数。
- 调用 ProcessMessage 方法时将 SoapMessageStage 设置为 BeforeSerialize。
- Web 服务器上的 ASP.NET 将返回值和输出参数序列化为 XML。
- 调用 ProcessMessage 方法时将 SoapMessageStage 设置为 AfterSerialize。
- ASP.NET 通过网络将 SOAP 响应消息发送回 Web 服务客户端。
步骤 6 已正确执行并记录了 SOAP XML。然后它不应该再做任何事情,直到服务器处理完调用,完成它需要的(步骤 10)并返回响应(步骤 13)。相反,它会立即在AfterSerialize 阶段再次调用ProcessMessage,但是这次流已经用完,并且在我尝试记录它时会引发异常。
根据演练,我应该使用ChainStream 方法,它应该在上面的第 5 步中运行。当我拨打电话时,它会运行两次,一次在BeforeDeserialize 之前,一次在AfterSerialize 之前。
我尝试将消息流复制到单独的流中并将其用于日志记录,如果BeforeDeserialize 已经运行,也可以设置某种状态,但问题仍然存在。
我仍然需要AfterSerialize 中的代码来处理发送回客户端的响应。但是,如果我尝试删除 AfterSerialize 中的代码并仅运行 BeforeDeserialize' I get aHTTP 400: Bad Request` 中的代码。
这一切都发生在实际的方法调用之前,所以我什至没有进入方法内部的代码(第 10 步)。
【问题讨论】:
-
好代码,在 VB 中,但很容易转换为 C#:github.com/Apress/pro-asp.net-1.1-in-vb-.net/blob/master/source/…
标签: c# asp.net web-services soap soap-extension