无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(二)
2016-07-28 17:16
591 查看
上一篇文章 "无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)"中,我们实现了监视每个页面的执行情况和调用WebService的简单信息。
这次我们继续深入一下SoapExtension的应用,在不改变Soap的WSDL文档的情况下,配合在Dotnet编写的WebService站点配置我们编写的SoapExtension,来穿透传输我们自定义的数据对象。由于SoapExtension是全局的,我们还要加一些标识来区分服务器是否已经配置了我们的SoapExtension,从而不影响其它的WebService调用。
在SoapExtension中,我想到有两种方案:
一种是直接在SoapMessage.Headers中插入自定义的SoapHeader对象,然后在客户端的序列化后,从SoapUnknownHeader中取出数据,然后反序列化成自定义的对象。
第二种是对SoapMessage.ContentType 添加一个额外的标识,在另一方检测这个标识,来从流中取出自己长度的数据。反序列化成自定义的对象。
我感觉第二种方案比较简单,高效,我们看一下代码:
/// <summary>
/// WSInvokeMonitorExtension 的摘要说明。
/// </summary>
public class StreamWSInvokeMonitorExtension : SoapExtension
{
private const string WSInvokeMonitorKey = "__WSInvokeMonitorKey__";
private const int MaxDataLength = 5 * 1024 * 1024; //5M
private XmlSerializer serializer = new XmlSerializer(typeof(DbConnInfo));
private Stream originStream;
private Stream usingStream = new MemoryStream();
private WSInvokeInfo invokeInfo = new WSInvokeInfo();
public override System.IO.Stream ChainStream(System.IO.Stream stream)
{
originStream = stream;
return usingStream;
}
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)
{
if(message is SoapClientMessage)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
this.invokeInfo.BeginInvokeTime = DateTime.Now;
this.invokeInfo.MethodName = message.MethodInfo.Name;
break;
case SoapMessageStage.AfterSerialize:
usingStream.Seek(0, SeekOrigin.Begin);
CopyStream(usingStream, originStream);
break;
case SoapMessageStage.BeforeDeserialize:
usingStream.SetLength(0);
CopyStream(originStream, usingStream);
usingStream.Seek(0, SeekOrigin.Begin);
if(message.ContentType.IndexOf("ExtInfo=true") != -1){
//先读出自己的信息
byte[] bytesFlags = new byte[]{66,69}; // BE 标识
if(usingStream.ReadByte() == bytesFlags[0]) //检验标志位
{
byte[] bytesLength = new byte[BitConverter.GetBytes((Int32)0).Length];
usingStream.Read(bytesLength,0, bytesLength.Length); //读取长度
int length = BitConverter.ToInt32(bytesLength,0);
if(length < MaxDataLength) //检验数据是否非法
{
if(usingStream.ReadByte() == bytesFlags[1]) //检验标志位
{
byte[] bytesData = new byte[length];
usingStream.Read(bytesData,0, bytesData.Length);
using(MemoryStream ms = new MemoryStream(bytesData))
{
DbConnInfo header = serializer.Deserialize(ms) as DbConnInfo;
Debug.WriteLine(header.Info);
}
break;
}
}
}
//数据不对,则重置流位置
usingStream.Position = 0;
}
break;
// About to call methods
case SoapMessageStage.AfterDeserialize:
//添加到Module记录
this.invokeInfo.EndInvokeTime = DateTime.Now;
PageInfo pageInfo = (PageInfo)HttpContext.Current.Items[WSInvokeMonitorKey] ;
if(pageInfo != null)
{
pageInfo.AppendInvokeInfo(this.invokeInfo);
}
break;
// After Method call
default:
throw new Exception("No stage such as this
[System.Serializable]
public class DbConnInfoSoapHeader
{
private string info;
public string Info
{
get { return info; }
set { info = value; }
}
public DbConnInfoSoapHeader()
{
}
public DbConnInfoSoapHeader(string info)
{
this.Info = info;
}
}
[System.Serializable]
public class SoapHeaderWrap : SoapHeader
{
private byte[] soapData = null;
private object data;
[XmlIgnoreAttribute]
[SoapIgnoreAttribute]
public object Data
{
get { return data; }
set
{
data = value;
soapData = null;
}
}
private string key;
[XmlAttribute]
public string Key
{
get { return key; }
set { key = value; }
}
[XmlAttribute]
public string TypeName
{
get{
return this.Data.GetType().AssemblyQualifiedName;
}
set{}
}
public byte[] SoapData
{
get
{
if(soapData == null && this.Data != null)
{
using(MemoryStream ms = new MemoryStream())
using(StreamWriter sw = new StreamWriter(ms,new UTF8Encoding(false)))
{
XmlSerializer serializer = new XmlSerializer(this.Data.GetType());
serializer.Serialize(sw, this.Data);
ms.Position = 0;
soapData = ms.ToArray();
}
}
return soapData;
}
set {
}
}
public SoapHeaderWrap(string key, object soapData)
{
this.Key = key;
this.Data = soapData;
}
public SoapHeaderWrap(string key)
:this(key,null)
{
}
public SoapHeaderWrap()
:this(string.Empty)
{
}
}
http://www.cnblogs.com/evlon/archive/2009/06/01/1493923.html
这次我们继续深入一下SoapExtension的应用,在不改变Soap的WSDL文档的情况下,配合在Dotnet编写的WebService站点配置我们编写的SoapExtension,来穿透传输我们自定义的数据对象。由于SoapExtension是全局的,我们还要加一些标识来区分服务器是否已经配置了我们的SoapExtension,从而不影响其它的WebService调用。
在SoapExtension中,我想到有两种方案:
一种是直接在SoapMessage.Headers中插入自定义的SoapHeader对象,然后在客户端的序列化后,从SoapUnknownHeader中取出数据,然后反序列化成自定义的对象。
第二种是对SoapMessage.ContentType 添加一个额外的标识,在另一方检测这个标识,来从流中取出自己长度的数据。反序列化成自定义的对象。
我感觉第二种方案比较简单,高效,我们看一下代码:
/// <summary>
/// WSInvokeMonitorExtension 的摘要说明。
/// </summary>
public class StreamWSInvokeMonitorExtension : SoapExtension
{
private const string WSInvokeMonitorKey = "__WSInvokeMonitorKey__";
private const int MaxDataLength = 5 * 1024 * 1024; //5M
private XmlSerializer serializer = new XmlSerializer(typeof(DbConnInfo));
private Stream originStream;
private Stream usingStream = new MemoryStream();
private WSInvokeInfo invokeInfo = new WSInvokeInfo();
public override System.IO.Stream ChainStream(System.IO.Stream stream)
{
originStream = stream;
return usingStream;
}
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)
{
if(message is SoapClientMessage)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
this.invokeInfo.BeginInvokeTime = DateTime.Now;
this.invokeInfo.MethodName = message.MethodInfo.Name;
break;
case SoapMessageStage.AfterSerialize:
usingStream.Seek(0, SeekOrigin.Begin);
CopyStream(usingStream, originStream);
break;
case SoapMessageStage.BeforeDeserialize:
usingStream.SetLength(0);
CopyStream(originStream, usingStream);
usingStream.Seek(0, SeekOrigin.Begin);
if(message.ContentType.IndexOf("ExtInfo=true") != -1){
//先读出自己的信息
byte[] bytesFlags = new byte[]{66,69}; // BE 标识
if(usingStream.ReadByte() == bytesFlags[0]) //检验标志位
{
byte[] bytesLength = new byte[BitConverter.GetBytes((Int32)0).Length];
usingStream.Read(bytesLength,0, bytesLength.Length); //读取长度
int length = BitConverter.ToInt32(bytesLength,0);
if(length < MaxDataLength) //检验数据是否非法
{
if(usingStream.ReadByte() == bytesFlags[1]) //检验标志位
{
byte[] bytesData = new byte[length];
usingStream.Read(bytesData,0, bytesData.Length);
using(MemoryStream ms = new MemoryStream(bytesData))
{
DbConnInfo header = serializer.Deserialize(ms) as DbConnInfo;
Debug.WriteLine(header.Info);
}
break;
}
}
}
//数据不对,则重置流位置
usingStream.Position = 0;
}
break;
// About to call methods
case SoapMessageStage.AfterDeserialize:
//添加到Module记录
this.invokeInfo.EndInvokeTime = DateTime.Now;
PageInfo pageInfo = (PageInfo)HttpContext.Current.Items[WSInvokeMonitorKey] ;
if(pageInfo != null)
{
pageInfo.AppendInvokeInfo(this.invokeInfo);
}
break;
// After Method call
default:
throw new Exception("No stage such as this
[System.Serializable]
public class DbConnInfoSoapHeader
{
private string info;
public string Info
{
get { return info; }
set { info = value; }
}
public DbConnInfoSoapHeader()
{
}
public DbConnInfoSoapHeader(string info)
{
this.Info = info;
}
}
[System.Serializable]
public class SoapHeaderWrap : SoapHeader
{
private byte[] soapData = null;
private object data;
[XmlIgnoreAttribute]
[SoapIgnoreAttribute]
public object Data
{
get { return data; }
set
{
data = value;
soapData = null;
}
}
private string key;
[XmlAttribute]
public string Key
{
get { return key; }
set { key = value; }
}
[XmlAttribute]
public string TypeName
{
get{
return this.Data.GetType().AssemblyQualifiedName;
}
set{}
}
public byte[] SoapData
{
get
{
if(soapData == null && this.Data != null)
{
using(MemoryStream ms = new MemoryStream())
using(StreamWriter sw = new StreamWriter(ms,new UTF8Encoding(false)))
{
XmlSerializer serializer = new XmlSerializer(this.Data.GetType());
serializer.Serialize(sw, this.Data);
ms.Position = 0;
soapData = ms.ToArray();
}
}
return soapData;
}
set {
}
}
public SoapHeaderWrap(string key, object soapData)
{
this.Key = key;
this.Data = soapData;
}
public SoapHeaderWrap(string key)
:this(key,null)
{
}
public SoapHeaderWrap()
:this(string.Empty)
{
}
}
http://www.cnblogs.com/evlon/archive/2009/06/01/1493923.html
相关文章推荐
- 利用iptables实现基于端口的网络流量统计
- 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)
- HttpClient自动处理Gzip,Deflate压缩
- HTTP状态码详解
- 网络通信
- 牛客网 7-28 网络基础 操作系统 编译与体系结构 30题知识点总结
- CentOS网络配置
- [转] 携程App网络服务通道治理和性能优化@2016
- Redhat 7.1使用CentOS 7 的Yum网络源
- BP神经网络python简单实现
- asp.net XMLHttpRequest 进度条以及lengthComputable always false的解决办法
- HTTP协议
- 获取网络状态
- Nohttp请求图片的两种简答的方式:普通请求以及缓存请求
- TCP/IP协议(2)——数据链路层
- Selenium源码分析之WebDriver
- VMWare三种网络模式图解
- 配置网络文件系统
- Nohttp网络请求数据,Post以及Get的简单实用以及设置缓存文字的的请求
- Forward和Redirect的比较(http转发请求的原理)