【学】SoapExtension 学习
SoapExtension.ChainStream 方法:
当在派生类中被重写时,允许 SOAP 扩展访问包含 SOAP 请求或响应的内存缓冲区。
命名空间:System.Web.Services.Protocols 程序集:System.Web.Services(在 system.web.services.dll 中)
ChainStream 确保具有最高优先级的 SOAP 扩展可以修改与通过网络发送或返回的 SOAP 消息最接近的实际数据。
SOAP 扩展应保存传入 ChainStream 的 Stream 和从 ChainStream 返回的 Stream 的引用。如果将 SOAP 扩展配置为与 XML Web services 方法一起运行,则传递到 ChainStream 中的 Stream 在 BeforeDeserializeSoapMessageStage 阶段包含已序列化的 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 扩展的配置情况,它可以找到有关采用 LogicalMethodInfo 的 SoapExtension 的 GetInitializer 方法中的 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 学习的更多相关文章
- 从零开始学深度学习mxnet教程:安装以及基本操作
一.导言 本教程适合对人工智能有一定的了解的同学,特别是对实际使⽤深度学习感兴趣的⼤学⽣.⼯程师和研究⼈员.但本教程并不要求你有任何深度学习或者机器学习的背景知识,我们将从头开始解释每⼀个概念.虽然深 ...
- 对比《动手学深度学习》 PDF代码+《神经网络与深度学习 》PDF
随着AlphaGo与李世石大战的落幕,人工智能成为话题焦点.AlphaGo背后的工作原理"深度学习"也跳入大众的视野.什么是深度学习,什么是神经网络,为何一段程序在精密的围棋大赛中 ...
- 【动手学深度学习】Jupyter notebook中 import mxnet出错
问题描述 打开d2l-zh目录,使用jupyter notebook打开文件运行,import mxnet 出现无法导入mxnet模块的问题, 但是命令行运行是可以导入mxnet模块的. 原因: 激活 ...
- 小白学习之pytorch框架(2)-动手学深度学习(begin-random.shuffle()、torch.index_select()、nn.Module、nn.Sequential())
在这向大家推荐一本书-花书-动手学深度学习pytorch版,原书用的深度学习框架是MXNet,这个框架经过Gluon重新再封装,使用风格非常接近pytorch,但是由于pytorch越来越火,个人又比 ...
- python之感知器-从零开始学深度学习
感知器-从零开始学深度学习 未来将是人工智能和大数据的时代,是各行各业使用人工智能在云上处理大数据的时代,深度学习将是新时代的一大利器,在此我将从零开始记录深度学习的学习历程. 我希望在学习过程中做到 ...
- 学java得这样学,学习确实也得这样
引言 软件开发之路是充满荆棘与挑战之路,也是充满希望之路.Java学习也是如此,没有捷径可走.梦想像<天龙八部>中虚竹一样被无崖子醍醐灌顶而轻松获得一甲子功力,是很不现实的.每天仰天大叫& ...
- 《linux就该这么学》学习笔记
本篇文章是根据刘遄老师的<linux就该这么学>中个人易忘知识点的读书笔记,结合的是个人弱点,可能不适合广大的网友同学,并在此声明本篇文章只是用于学习之用,绝无侵犯版权之意 linux就该 ...
- 8年开发老司机告诉你啥是java开发?如何学?学习什么内容?
什么是Java? 我从Java的官网上抄下来下面这段话:97% 的企业桌面运行 Java美国有 89% 的桌面(或计算机)运行 Java全球有 900 万 Java 开发人员开发人员的头号选择排名第一 ...
- [跟我学spring学习笔记][更多DI知识]
延迟初始化Bean 定义: 延迟初始化也叫做惰性初始化,指不提前初始化Bean,在真正使用时才创建并初始化Bean 如何延迟: 配置方式很简单只需在标签上指定 “lazy-init” 属性值为“tru ...
随机推荐
- Free download
http://blogs.msdn.com/b/mssmallbiz/archive/2014/07/07/largest-collection-of-free-microsoft-ebooks-ev ...
- hibernate 问题集
1.Could not obtain transaction-synchronized Session for current thread 解决方法: 在web.xml中加入如下配置: <fi ...
- Spring-Context之二:使用Spring提供的测试框架进行测试
Spring框架是无侵入性的,所以你的代码可以完全是POJO(plain old java object),直接使用Junit就可以完成大部分的单元测试.但是在集成测试方面就比较吃力了.单元测试层面你 ...
- javax.persistence.PersistenceException: No Persistence provider for EntityManager named ...
控制台下输出信息 原因:persistence.xml必须放在src下META-INF里面. 若误放在其他路径,就会迷路.
- 基于slideout.js实现的移动端侧边栏滑动特效
HTML5现在本领太大了,PC端已经无法满足它的胃口了,它将强势攻入移动端,所以移动端中各种特效也得基于HTML5实现,看看我们将要介绍的slideout.js,能帮我们实现怎么样的侧边栏滑动特效呢~ ...
- Fiddler 修改返回内容 OnBeforeResponse 无效 没用
Fiddler自定义脚本可以实现很强大的内容替换,包括很有意义的——修改返回内容. 具体的方法可以参考官网:http://docs.telerik.com/fiddler/KnowledgeBase/ ...
- ADO.NET笔记20160322
####ADO.NET ####1 启用sa验证与窗体相关知识 - 启用sa验证 - ShowDialog() ---- ####2 连接字符串 Data Source=服务器 ...
- mysql忘记密码重置(mac)
setp1: 苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) step2:进入终端输入:cd /usr/local/ ...
- HOWTO - Basic MSI安装包在安装运行过程中如何获取完整源路径
有朋友问到如何在一个Windows Installer安装包中获取安装包源路径,就是在安装包运行过程中动态获取*.msi所在完整路径. 这个问题分两类,如果我们的安装包只是一个*.msi安装文件,那么 ...
- Swift - UITableViewCell倒计时重用解决方案
Swift - UITableViewCell倒计时重用解决方案 效果 源码 https://github.com/YouXianMing/Swift-Animations // // CountDo ...
