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. 在stackoverflow上使用markdown

    stackoverflow流派的markdown. Code and Preformatted Text 缩进四个空格,就可以写代码片段了 def hello(): print "hello ...

  2. [外挂4] 用CE查找棋盘基址

    a.找棋盘数据基址 b.分析棋盘数据结构 综合使用搜索技巧,这要看你的聪明才智啦! [如本例:首先精确查找0,然后点一下左上角的一个,再次筛选出变化的,重开盘,再搜变化的,发现期盼规律为值为0表示没有 ...

  3. [BTS] Correct the specified Action, or refer to the documentation on the allowed formats for the Actions

    A message sent to adapter "WCF-SAP" on send port "CNILG.iHouse.SAP.WCFSAP" with ...

  4. paip.输入法英文词库的处理 python 代码 o4

    paip.输入法英文词库的处理 python 代码 o4 目标是eng>>>中文>>atian 当输入非atian词的时候儿,能打印出 atian pinyin > ...

  5. python实现curl功能

    之前写过一篇文章关于python CURL模块的,在这里我们从urllib来实现同样的功能.具体代码如下: import urllib import urllib2 import json #发起请求 ...

  6. 24单行插入与批量插入-insert(必学)-天轰穿sqlserver视频教程

    大纲:insert语句,简单插入数据与批量插入数据 为了冲优酷的访问量,所以这里只放优酷的地址了,其实其他网站还是都传了的哈. 代码下载http://www.cnthc.com/?/article/1 ...

  7. Linux Netcat 命令——网络工具中的瑞士军刀

    原文:http://www.oschina.net/translate/linux-netcat-command netcat是网络工具中的瑞士军刀,它能通过TCP和UDP在网络中读写数据.通过与其他 ...

  8. 传递给数据库 'master' 中的日志扫描操作的日志扫描号无效

    错误:连接数据库的时候提示:SQL Server 检测到基于一致性的逻辑 I/O 错误 校验和不正确 C:\Documents and Settings\Administrator>" ...

  9. INFO - InstallShield中的InstallScript工程Setup.exe /s的使用细节

    在InstallShield的各种工程类型中,Basic MSI工程Build出的安装包基于Windows Installer标准,所以默认就支持静默安装(至于如何静默安装,请自行补充相关知识).而对 ...

  10. Javascript基础恶补

    1.字符集:Javascript采用Unicode字符集,支持地球上所有在用的语言. 2.区分大小写:Javascript区分大小写,HTML不区分大小写. 3.空格.换行.格式控制符:Javascr ...