我正在尝试为对我的 ASP.NET Web 服务的所有 SOAP 方法调用创建一个日志记录服务。我一直在查看 来自控制台应用程序的 Log SOAP 消息以及 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
,但随后ProcessMessage
在阶段再次调用,AfterSerialize
到那时流被使用并且不再包含任何数据。
根据使用 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)。相反,它会立即ProcessMessage
在AfterSerialize
舞台上再次调用,但这一次流已经用完,当我尝试记录它时会引发异常。
根据演练,我应该使用该ChainStream
方法,并且应该在上面的步骤 5 中运行。当我拨打电话时,它会运行两次,一次之前BeforeDeserialize
,一次之前AfterSerialize
。
BeforeDeserialize
我尝试将消息流复制到一个单独的流并将其用于日志记录,如果已经运行,也可以设置某种状态,但问题仍然存在。
我仍然需要代码AfterSerialize
来处理发送回客户端的响应。但是,如果我尝试删除我的代码AfterSerialize
并仅在BeforeDeserialize' I get a
HTTP 400: Bad Request` 中运行代码。
这一切都发生在实际的方法调用之前,所以我什至从未接触过方法内部的代码(第 10 步)。