程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> 無侵入方面編程-用HttpModule+SoapExtension監視頁面執行參數(二)

無侵入方面編程-用HttpModule+SoapExtension監視頁面執行參數(二)

編輯:關於ASP.NET

上一篇文章 "無侵入方面編程-用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");
}

}
else if(message is SoapServerMessage)
{
switch (message.Stage)
{
// Incoming from client
case SoapMessageStage.BeforeDeserialize:
usingStream.SetLength(0);
CopyStream (originStream, usingStream);
usingStream.Seek(0, SeekOrigin.Begin);

break;

// About to call methods
case SoapMessageStage.AfterDeserialize:
break;

// After Method call
case SoapMessageStage.BeforeSerialize:

//設置自定義Header
usingStream.SetLength (0);  //清空並先寫入自定義的信息


byte[] bytesData = null;
using (MemoryStream ms = new MemoryStream())
{
serializer.Serialize(ms,new DbConnInfo ("3個數據庫連接"));  //服務端自定義的信息
bytesData = ms.ToArray();
}
message.ContentType += ";ExtInfo=true";
//寫入標識
byte[] bytesFlags = new byte[]{66,69}; // BE
usingStream.WriteByte(bytesFlags[0]);

//寫入長度
byte[] dataLength = BitConverter.GetBytes(bytesData.Length);
usingStream.Write(dataLength, 0, dataLength.Length);

//再寫入標志
usingStream.WriteByte(bytesFlags[1]);

//寫入數據
usingStream.Write (bytesData, 0, bytesData.Length);

break;

// Outgoing to other
case SoapMessageStage.AfterSerialize:
usingStream.Seek(0, SeekOrigin.Begin);
CopyStream(usingStream, originStream);
break;

default:
throw new Exception("No stage such as this");
}

}
}


private void CopyStream(Stream src, Stream des)
{
byte[] buf = new byte [1024];
int length = 0;
do
{
length = src.Read(buf,0,buf.Length);
des.Write(buf,0,length);
} while (length == buf.Length);

}
}

[System.Serializable]
public class DbConnInfo
{
private string info;
public string Info
{
get { return info; }
set { info = value; }
}

public DbConnInfo()
{
}

public DbConnInfo(string info)
{
this.Info = info;
}

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved