http://msdn.microsoft.com/zh-cn/library/System.Web.Services.Protocols.SoapExtension_methods(v=vs.80).aspx

SoapExtension.ChainStream 方法:

当在派生类中被重写时,允许 SOAP 扩展访问包含 SOAP 请求或响应的内存缓冲区。

命名空间:System.Web.Services.Protocols 程序集:System.Web.Services(在 system.web.services.dll 中)

ChainStream 确保具有最高优先级的 SOAP 扩展可以修改与通过网络发送或返回的 SOAP 消息最接近的实际数据。

SOAP 扩展应保存传入 ChainStreamStream 和从 ChainStream 返回的 Stream 的引用。如果将 SOAP 扩展配置为与 XML Web services 方法一起运行,则传递到 ChainStream 中的 StreamBeforeDeserializeSoapMessageStage 阶段包含已序列化的 SOAP 请求。同样,当发生序列化时,从 ChainStream 返回的 Stream 引用被写入,从而在 AfterSerializeSoapMessageStage 中包含已序列化的 SOAP 响应。

public override Stream ChainStream( Stream stream ){
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}

SoapMessageStage 枚举:

  成员名称 说明
AfterDeserialize 恰好在将 SoapMessage 从 SOAP 消息反序列化到对象之后的阶段。

SoapClientMessage 处理过程中,AfterDeserialize 阶段发生在 SOAP 消息(包含来自 XML Web services 方法调用的响应)反序列化到对象之后,但在客户端接收到反序列化结果之前。

SoapServerMessage 处理过程中,AfterDeserialize 阶段出现在这种情形下:在包含 SOAP 消息的网络请求(表示已将 XML Web services 方法调用反序列化为对象)之后,对对象执行方法(表示 XML Web services 方法已调用)之前。

AfterSerialize 恰好在序列化 SoapMessage 之后,但在通过网络发送 SOAP 消息之前的阶段。

SoapClientMessage 处理过程中,AfterSerialize 阶段发生在客户端调用 XML Web services 方法并且参数序列化到 XML 之后,但在包含此 XML 的 SOAP 消息被通过网络发送之前。

SoapServerMessage 处理过程中,AfterSerialize 阶段发生在 XML Web services 方法返回并且所有返回值都序列化到 XML 之后,但在包含此 XML 的 SOAP 消息被通过网络发送之前。

BeforeDeserialize 恰好在将 SoapMessage 从通过网络发送的 SOAP 消息反序列化到对象之前的阶段。

SoapClientMessage 处理过程中,BeforeDeserialize 阶段发生在接收到来自 XML Web services 方法调用的网络响应之后,但在包含 SOAP 消息的响应反序列化到对象之前。

SoapServerMessage 处理过程中,BeforeDeserialize 阶段发生在 Web 服务器接收到网络请求(包含 XML Web services 方法调用的 SOAP 消息)之后,但在 SOAP 消息反序列化到对象之前。

BeforeSerialize 恰好在序列化 SoapMessage 之前的阶段。

SoapClientMessage 处理过程中,BeforeSerialize 阶段发生在客户端调用 XML Web services 方法之后,但在该调用被序列化之前。

SoapServerMessage 处理过程中,BeforeSerialize 阶段发生在对 XML Web services 方法的调用返回之后,但在将返回值序列化并通过网络发送回客户端之前。

// Process the SOAP message received and write to log file.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput( message );
break;
case SoapMessageStage.BeforeDeserialize:
WriteInput( message );
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}

LogicalMethodInfo 类:

表示 XML Web services 方法的属性 (Attribute) 和元数据。无法继承此类。

LogicalMethodInfo 主要由 SOAP 扩展用来询问 SOAP 扩展被配置为与之一起运行的 XML Web services 方法的详细信息。根据 SOAP 扩展的配置情况,它可以找到有关采用 LogicalMethodInfoSoapExtensionGetInitializer 方法中的 XML Web services 方法的详细信息。LogicalMethodInfo 通过使用 GetCustomAttributes 属性 (Property) 访问应用于 XML Web services 方法的 Parameters 属性 (Property) 和任何自定义属性 (Attribute) 来提供诸如 XML Web services 方法参数等详细信息。

// Process the SOAP message received and write to log file.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput((SoapServerMessage)message);
break;
case SoapMessageStage.BeforeDeserialize:
WriteInput((SoapServerMessage)message);
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
} // Write the contents of the incoming SOAP message to the log file.
public void WriteInput(SoapServerMessage message)
{
// Utility method to copy the contents of one stream to another.
Copy(oldStream, newStream);
FileStream myFileStream = new FileStream(filename, FileMode.Append, FileAccess.Write);
StreamWriter myStreamWriter = new StreamWriter(myFileStream);
myStreamWriter.WriteLine("================================== Request at "
+ DateTime.Now);
myStreamWriter.WriteLine("The method that has been invoked is : ");
myStreamWriter.WriteLine("\t" + message.MethodInfo.Name);
myStreamWriter.WriteLine("The contents of the SOAP envelope are : ");
myStreamWriter.Flush();
newStream.Position = ;
Copy(newStream, myFileStream);
myFileStream.Close();
newStream.Position = ;
} // Write the contents of the outgoing SOAP message to the log file.
public void WriteOutput(SoapServerMessage message)
{
newStream.Position = ;
FileStream myFileStream = new FileStream(filename, FileMode.Append, FileAccess.Write);
StreamWriter myStreamWriter = new StreamWriter(myFileStream);
myStreamWriter.WriteLine("---------------------------------- Response at "
+ DateTime.Now);
myStreamWriter.Flush();
// Utility method to copy the contents of one stream to another.
Copy(newStream, myFileStream);
myFileStream.Close();
newStream.Position = ;
Copy(newStream, oldStream);
}

SoapExtensionAttribute 类:

当在派生类中重写时,指定 SOAP 扩展应该与 XML Web services 方法一起运行。

使用 ASP.NET 创建的 XML Web services 方法可以配置为与 SOAP 扩展一起运行,方法是将一项属性应用于该 XML Web services 方法。将自定义扩展属性添加到 XML Web services 方法或客户端代理类中的方法后,ASP.NET 将在适当的时间调用关联的扩展。扩展属性是从 SoapExtensionAttribute 派生的自定义属性类。派生属性必须重写 ExtensionType 属性以返回与该属性关联的扩展的类型。

下面的 TraceExtensionAttribute 类从 SoapExtensionAttribute 派生,以支持将该属性应用于 XML Web services 方法或 XML Web services 客户端代理类中的方法。当应用于上述两种方法中的任意一个时,TraceExtension SOAP 扩展将与该方法一起运行。

// Create a SoapExtensionAttribute for a SOAP extension that can be
// applied to an XML Web service method.
[AttributeUsage(AttributeTargets.Method)]
public class TraceExtensionAttribute : SoapExtensionAttribute { private string myFilename;
private int myPriority; // Set the name of the log file were SOAP messages will be stored.
public TraceExtensionAttribute() : base()
{
myFilename = "C:\\logClient.txt";
} // Return the type of 'TraceExtension' class.
public override Type ExtensionType
{
get
{
return typeof(TraceExtension);
}
} // User can set priority of the 'SoapExtension'.
public override int Priority
{
get
{
return myPriority;
}
set
{
myPriority = value;
}
} public string Filename
{
get
{
return myFilename;
}
set
{
myFilename = value;
}
}
}

【摘】http://www.cnblogs.com/wobushixiaocai/archive/2008/04/11/1148196.html

1、SOAP扩展是在SoapMessage (SoapClientMessage和SoapServerMessage类型)传输过程中对其SOAP消息处理过程的拦截器,其可以在SoapMessage的四个阶段进行拦截并且插入代码,这四个阶段分别是BeforeSerialize"AfterSerialize"BeforeDeserialize和AfterDeserialize。

2、 在整个WebService访问过程中,ChainStream一共执行四次,在客户端执行两次,在服务器端执行两次。ChainStream的调用是按照Soap扩展的高优先级到低优先级的调用顺序依次调用的。

3、 每次SoapMessage的Stage状态发生改变时都会调用SoapExtension的ProcessMessage。所以这个函数一共执行8次。其中需要特别注意的是,不同优先级的Soap扩展在Soap消息传输的不同阶段其调用顺序是不一样的,具体可以分为两个阶段:即Serialize阶段,其调用是按照Soap扩展的优先级从低到高执行的,在Deserialize阶段,其调用是按照Soap扩展优先级从高到低执行的。

项目实践:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services.Protocols;
using System.IO;
using System.Xml;
using BillingWS.Common; namespace BillingWS.BusinessLogic
{
public class TraceExtension : SoapExtension
{
private Stream oldStream;
private Stream newStream; private string category;
private string methodName; private XmlDocument xmlRequest;
/// <summary>
/// Gets the outgoing XML request sent to PayPal
/// </summary>
private XmlDocument XmlRequest
{
get { return xmlRequest; }
} private XmlDocument xmlResponse;
/// <summary>
/// Gets the incoming XML response sent from PayPal
/// </summary>
private XmlDocument XmlResponse
{
get { return xmlResponse; }
} /// <summary>
/// Save the Stream representing the SOAP request
/// or SOAP response into a local memory buffer.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public override Stream ChainStream(Stream stream)
{
oldStream = stream;
newStream = new MemoryStream();
return newStream;
} public override object GetInitializer(Type serviceType)
{
return null;
} public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null;
} public override void Initialize(object initializer)
{ } public override void ProcessMessage(SoapMessage message)
{
try
{
string serviceName = message.MethodInfo.DeclaringType.Name;
category = Common.PublicEnums.WSCallSource.Zuora.ToString(); switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break; case SoapMessageStage.AfterSerialize:
xmlRequest = GetSoapEnvelope(newStream);
CopyStream(newStream, oldStream);
break; case SoapMessageStage.BeforeDeserialize:
CopyStream(oldStream, newStream);
xmlResponse = GetSoapEnvelope(newStream); if (serviceName.IndexOf("ZuoraService") != -)
{
methodName = message.MethodInfo.Name;
LogMessage();
}
break; case SoapMessageStage.AfterDeserialize:
break;
} }
catch (Exception ex)
{
ZuoraException exception = new ZuoraException(PublicEnums.ExceptionType.LogTraceFailed, "ProcessMessage Failed:" + ex.Message, ex);
exception.Log();
}
} #region Method
public void LogMessage()
{
try
{
HttpContext content = HttpContext.Current;
if (content != null && content.Session != null)
{
if (content.Session[PublicConstants.SESSION_TRANSACTIONLOGID] != null)
{
Guid transactionId = new Guid(content.Session[PublicConstants.SESSION_TRANSACTIONLOGID].ToString()); TransactionConverter converter = new TransactionConverter(transactionId, category, methodName, xmlRequest, xmlResponse);
converter.LogDB();
}
}
}
catch (Exception ex)
{
ZuoraException exception = new ZuoraException(PublicEnums.ExceptionType.LogTraceFailed, "LogMessage Failed:" + ex.Message, ex);
exception.Log();
}
}
private XmlDocument GetSoapEnvelope(Stream stream)
{
XmlDocument xml = new XmlDocument();
try
{
stream.Position = ;
StreamReader reader = new StreamReader(stream);
xml.LoadXml(reader.ReadToEnd());
stream.Position = ;
}
catch (Exception ex)
{
ZuoraException exception = new ZuoraException(PublicEnums.ExceptionType.LogTraceFailed, "GetSoapEnvelope Failed:" + ex.Message, ex);
exception.Log();
}
return xml;
} /// <summary>
/// Copies a stream.
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
private void CopyStream(Stream from, Stream to)
{
try
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
catch (Exception ex)
{
ZuoraException exception = new ZuoraException(PublicEnums.ExceptionType.LogTraceFailed, "CopyStream Failed:" + ex.Message, ex);
exception.Log();
}
}
#endregion
}
}

【学】SoapExtension 学习的更多相关文章

  1. 从零开始学深度学习mxnet教程:安装以及基本操作

    一.导言 本教程适合对人工智能有一定的了解的同学,特别是对实际使⽤深度学习感兴趣的⼤学⽣.⼯程师和研究⼈员.但本教程并不要求你有任何深度学习或者机器学习的背景知识,我们将从头开始解释每⼀个概念.虽然深 ...

  2. 对比《动手学深度学习》 PDF代码+《神经网络与深度学习 》PDF

    随着AlphaGo与李世石大战的落幕,人工智能成为话题焦点.AlphaGo背后的工作原理"深度学习"也跳入大众的视野.什么是深度学习,什么是神经网络,为何一段程序在精密的围棋大赛中 ...

  3. 【动手学深度学习】Jupyter notebook中 import mxnet出错

    问题描述 打开d2l-zh目录,使用jupyter notebook打开文件运行,import mxnet 出现无法导入mxnet模块的问题, 但是命令行运行是可以导入mxnet模块的. 原因: 激活 ...

  4. 小白学习之pytorch框架(2)-动手学深度学习(begin-random.shuffle()、torch.index_select()、nn.Module、nn.Sequential())

    在这向大家推荐一本书-花书-动手学深度学习pytorch版,原书用的深度学习框架是MXNet,这个框架经过Gluon重新再封装,使用风格非常接近pytorch,但是由于pytorch越来越火,个人又比 ...

  5. python之感知器-从零开始学深度学习

    感知器-从零开始学深度学习 未来将是人工智能和大数据的时代,是各行各业使用人工智能在云上处理大数据的时代,深度学习将是新时代的一大利器,在此我将从零开始记录深度学习的学习历程. 我希望在学习过程中做到 ...

  6. 学java得这样学,学习确实也得这样

    引言 软件开发之路是充满荆棘与挑战之路,也是充满希望之路.Java学习也是如此,没有捷径可走.梦想像<天龙八部>中虚竹一样被无崖子醍醐灌顶而轻松获得一甲子功力,是很不现实的.每天仰天大叫& ...

  7. 《linux就该这么学》学习笔记

    本篇文章是根据刘遄老师的<linux就该这么学>中个人易忘知识点的读书笔记,结合的是个人弱点,可能不适合广大的网友同学,并在此声明本篇文章只是用于学习之用,绝无侵犯版权之意 linux就该 ...

  8. 8年开发老司机告诉你啥是java开发?如何学?学习什么内容?

    什么是Java? 我从Java的官网上抄下来下面这段话:97% 的企业桌面运行 Java美国有 89% 的桌面(或计算机)运行 Java全球有 900 万 Java 开发人员开发人员的头号选择排名第一 ...

  9. [跟我学spring学习笔记][更多DI知识]

    延迟初始化Bean 定义: 延迟初始化也叫做惰性初始化,指不提前初始化Bean,在真正使用时才创建并初始化Bean 如何延迟: 配置方式很简单只需在标签上指定 “lazy-init” 属性值为“tru ...

随机推荐

  1. Jenkins pipeline 入门到精通系列文章

    Jenkins2 入门到精通系列文章. Jenkins2 下载与启动jenkins2 插件安装jenkins2 hellopipelinejenkins2 pipeline介绍jenkins2 jav ...

  2. PHP 开发社区微信服务号实战图解

    本博文就月初刚上线的微信服务号,图文进行总结分享给大家. 去年年底,我所在的团队讨论要开发微信号,话题由此拉开: 原来有一个3年前注册的微信号,但是后台操作无法从“订阅号”变更为“服务号”,随即找腾讯 ...

  3. Windows Server 2008R2配置MySQL Cluster

    目录 配置环境 相关知识 配置过程 配置 ini参数解释 启动集群 检查配置 同步测试 故障测试 写在之后 配置环境 VMware:(版本10.0.01) 操作系统:Windows Server 20 ...

  4. 菜鸟学习WCF笔记-Address

    终结点是WCF最为核心的对象,因为它承载了所有通信功能.服务通过相应的终结点发布出来,客户端通过与之匹配的终结点对服务进行调用.终结点有地址.绑定和契约ABC三要素构成. Address  作为终结点 ...

  5. jQuery实现Checkbox中项目开发全选全不选的使用

    <html> <head> <meta charset="utf-8"> <title>Checkbox的练习</title& ...

  6. Linux中如何产生core文件?

      在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息).使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数.   1.core文件 ...

  7. python读文件

    第一种方法 #encoding=utf-8 file = open("./man_data.txt","r") try: print file.read() f ...

  8. 隐知识:reloadData 方法之后,view并不会立即更新其contentSize

    在使用UITableView .UICollectionView ,调用reloadData方法之后,并不立即更新其contentSize.原因如下:http://jacksonriver.com/n ...

  9. Activiti保存流程图时diagrms中没有生成png解决办法

    window ——> preferences——>activiti——>save——>选中create process definition image when saving ...

  10. SQL Server查看所有表大小、表行数和占用空间信息

    一.查看表名和对应的数据行数select  a.name as '表名',b.rows as '表数据行数'from sysobjects a inner join sysindexes bon a. ...