<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WCF進階:將消息正文Base64編碼

         大家好,很久沒有寫博文了,平時也是在用WCF做著項目,但不寫文,總是感覺對技術的把握不夠清楚全面。同時更主要的是和大家缺少很多溝通,有愧疚感呀。好了,閑話少敘,從今天起,我將推出WCF進階系列博文。和大家一起來繼續學習WCF。歡迎板磚!

         WCF有一套標準的安全機制,但使用過的朋友都清楚,這些機制在編程和配置上都非常麻煩,重要的是還需要證書,這也不太容易部署,本文講述如何通過自定義Formatter將消息正文Base64編碼傳輸,雖然安全級別不是太高,但也能夠防止消息正文已明文形式傳輸。保護消息的秘密性。而且使用起來非常方便。通過學習本文,您能了解如下內容:1) 如何自定義消息記錄 2) 如何修改消息 3) 如何實現自定義編碼器。在WCF中消息是在通道堆棧中傳遞的,每個通道都可以對消息進行加工處理,上一個通道的輸出為下一個通道的輸入,而在消息通道中,WCF還開放很多Inspector,比如MessageInspector和ParamterInspector,通過這些攔截器,我們能實現自定義的消息記錄和修改。WCF還提供了自定義Formatter的接口來實現自定義的編碼器。我們就是利用WCF的上述接口來自定義編碼,將消息正文編碼為Base64的字符串,并且通過自定義的MessageInspector來記錄消息內容。

      先看一下如何實現自定義MessageInspector,在WCF中提供了兩個接口: IClientMessageInspector和IDispatchMessageInspector,分別用于截取客戶端消息和服務端消息。這兩個接口的定義如下:

      public interface IClientMessageInspector

      {

      // Methods

      void AfterReceiveReply(ref Message reply, object correlationState);

      object BeforeSendRequest(ref Message request, IClientChannel channel);

      } 

       

      public interface IDispatchMessageInspector

      {

      // Methods

      object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);

      void BeforeSendReply(ref Message reply, object correlationState);

      } 

       

      實現了上述兩個接口的類即是自定義的MessageInspector。客戶端ClientRuntime對象和服務端的DispatchRumtime對象中管理中MessageInspectors集合,我們將自定義的MessageInspector實例化對象添加到集合中,MessageInspector即可生效。這個過程需要實現自定義的IEndpointBehavior。該接口的定義為:

      public interface IEndpointBehavior

      {

      // Methods

      void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);

      void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);

      void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher);

      void Validate(ServiceEndpoint endpoint);

      } 

       

      下面有兩個個代碼片段,分別實現了自定義MessageInspector和EndpointBehavior

      1 . 自定義的MessageInspector:

       

       

      代碼
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Dispatcher;

      namespace RobinLib
      {
          
      public class MessageInspector : IClientMessageInspector,IDispatchMessageInspector
          {
              
      #region IClientMessageInspector 成員

              
      public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
              {
                  Console.WriteLine(reply.ToString());
              }

              
      public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
              {
                  Console.WriteLine(request.ToString());
                  
      return null;
              }

              
      #endregion

              
      #region IDispatchMessageInspector 成員

              
      public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
              {
                  Console.WriteLine(request.ToString());
                  
      return null;
              }

              
      public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
              {
                  Console.WriteLine(reply.ToString());
              }

              
      #endregion
          }
      }

       

       

      2 . 用于自定義消息記錄的自定義EndpointBehavior

       

      代碼
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Description;
      using System.ServiceModel.Dispatcher;

      namespace RobinLib
      {
          
      public class OutputMessageBehavior : IEndpointBehavior
          {

              
      #region IEndpointBehavior 成員

              
      public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
              {

              }

              
      public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
              {
                  clientRuntime.MessageInspectors.Add(
      new MessageInspector());
              }

              
      public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
              {
                  endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
      new MessageInspector());
              }

              
      public void Validate(ServiceEndpoint endpoint)
              {

              }

              
      #endregion
          }
      }

       

       

      實現了上述兩個類,我們就基本搞定了第一個問題:如何自定義消息記錄,下面我們來探討如何實現自定義Formatter。WCF提供了IClientMessageFormatter和IDispatchMessageFormatter兩個接口類分別用于客戶端和服務端的編解碼。

       

      public interface IClientMessageFormatter

      {

      // Methods

      object DeserializeReply(Message message, object[] parameters);

      Message SerializeRequest(MessageVersion messageVersion, object[] parameters);

      } 

       

      public interface IDispatchMessageFormatter

      {

      // Methods

      void DeserializeRequest(Message message, object[] parameters);

      Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result);

      } 

       

      實現這兩個接口,就實現了自定義的編碼器,但說句實在的,要實現完整通用的編碼器并不是容易的事情。偷偷通過.Net Reflactor查看了下.Net Framework源碼,缺省的實現代碼量至少也有上千行了。我這次實現自定義的Formatter,其實是修改缺省Formatter編碼好的消息,將消息的正文<S:Body></S:Body>中的內容轉變成Base64字符串,然后在編碼到另外的消息中的形式來實現自定義消息編碼的。這個過程有三個主要的難點:

      1. 如何創建自定義的Message對象

       

      1. 如何將原始消息轉換為Base64正文的消息
      2. 如何從Base64正文消息轉換為原始消息。

       

      我通過三個函數,分別實現了這三個難點:

       

      1. 自定義的BodyWriter 

       

      代碼
      using System; 

      using System.Collections.Generic; 

      using System.Linq; 

      using System.Text; 

      using System.ServiceModel.Channels; 

      using System.Xml; 

       

      namespace RobinLib 



      public class MyBodyWriter : BodyWriter 



      string body = ""

      XmlDocument doc; 

      public MyBodyWriter(string body) 

      base(true



      this.body = body; 



       

      public MyBodyWriter(XmlDocument doc) 

      base(true



      this.doc = doc; 



       

      protected override void OnWriteBodyContents(XmlDictionaryWriter writer) 



      XmlWriterSettings setting 
      = new XmlWriterSettings(); 

      setting.NewLineHandling 
      = NewLineHandling.Entitize; 

      setting.CheckCharacters 
      = false

      if (!string.IsNullOrEmpty(body)) 



      writer.WriteRaw(body); 



      if (doc != null



      doc.WriteContentTo(writer); 

      writer.Flush(); 









       

      2. 轉換原始消息為Base64正文的消息

       

      代碼
      private Message Base64BodyMessage(Message ora_msg) 



      MemoryStream ms 
      = new MemoryStream(); 

      XmlDictionaryWriter writer 
      = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8); 

      ora_msg.WriteBodyContents(writer); 

      writer.Flush(); 

      string body = System.Text.Encoding.UTF8.GetString(ms.GetBuffer()); 

      byte[] buffer = System.Text.Encoding.UTF8.GetBytes(body); 

      body 
      = Convert.ToBase64String(buffer); 

      Message msg 
      = Message.CreateMessage(ora_msg.Version, ora_msg.Headers.Action, new MyBodyWriter(body)); 

      ora_msg.Close(); 

      return msg; 



       

       

      3. 轉換Base64消息為原始消息

       

       

      代碼
      private Message RestoreMessageFormBase64Message(Message message) 



      Message msg 
      = null

      MemoryStream ms 
      = new MemoryStream(); 

      XmlDictionaryWriter writer 
      = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8); 

      message.WriteBody(writer); 

      writer.Flush(); 

      string body = System.Text.Encoding.UTF8.GetString(ms.GetBuffer()); 

      int index = body.IndexOf(">"); 

      int index2 = body.IndexOf("</"); 

      body 
      = body.Substring(index + 1, index2 - index - 1); 

      byte[] buffer2 = Convert.FromBase64String(body); 

      body 
      = System.Text.Encoding.UTF8.GetString(buffer2); 

      XmlDocument doc 
      = new XmlDocument(); 

      doc.LoadXml(body); 

      msg 
      = Message.CreateMessage(message.Version, message.Headers.Action, new MyBodyWriter(doc)); 

      msg.Headers.FaultTo 
      = message.Headers.FaultTo; 

      msg.Headers.From 
      = message.Headers.From; 

      msg.Headers.MessageId 
      = message.Headers.MessageId; 

      msg.Headers.RelatesTo 
      = message.Headers.RelatesTo; 

      msg.Headers.ReplyTo 
      = message.Headers.ReplyTo; 

      msg.Headers.To 
      = message.Headers.To; 

      foreach (var mh in message.Headers) 



      if (mh is MessageHeader) 



      if (mh.Name != "Action" && mh.Name != "FaultTo" && mh.Name != "From" && mh.Name != "MessageID" && mh.Name != "RelatesTo" && mh.Name != "ReplyTo" && mh.Name != "To"



      msg.Headers.Add(mh 
      as MessageHeader); 







      msg.Properties.Clear(); 

      foreach (var p in message.Properties) 



      msg.Properties[p.Key] 
      = p.Value; 



      return msg; 



       

      完整的代碼見附件。實現了自定義的Formatter,我們還需要通過擴展OperationBehavior,將應用Formatter,因此我們創建了Base64BodyBehavior,代碼為:

       

      代碼
      using System; 

      using System.Collections.Generic; 

      using System.Linq; 

      using System.Text; 

      using System.ServiceModel.Description; 

       

      namespace RobinLib 



      /// <summary> 

      /// 將消息主題序列為base64的OperationBehavior 

      /// </summary> 

      public class Base64BodyBehavior : IOperationBehavior 



      #region IOperationBehavior 成員 

       

      public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 



       



       

      public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation) 



      clientOperation.SerializeRequest 
      = true

      clientOperation.DeserializeReply 
      = true

      clientOperation.Formatter 
      = new Base64BodyFormatter(clientOperation.Formatter); 



       

      public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation) 



      dispatchOperation.DeserializeRequest 
      = true

      dispatchOperation.SerializeReply 
      = true

      dispatchOperation.Formatter 
      = new Base64BodyFormatter(dispatchOperation.Formatter); 



       

      public void Validate(OperationDescription operationDescription) 



       



       

      #endregion 





       

       

      好了,目前我們已經將自定義消息記錄和自定義編碼器基本實現了,現在就涉及到如何在服務器代碼和客戶端代碼中添加EndpointBehavior和OperationBehavior,我們用純代碼的形式做了一下實現, 

       

      1. 在服務器托管代碼中:

       

       

      代碼
      using System; 

      using System.Collections.Generic; 

      using System.Linq; 

      using System.Text; 

      using System.ServiceModel; 

       

      namespace Robin_Wcf_Host_Console 



      class Program 



      static void Main(string[] args) 



      //服務地址 

      Uri baseAddress 
      = new Uri("net.tcp://127.0.0.1:8081/Robin_Wcf_Formatter"); 

      ServiceHost host 
      = new ServiceHost(typeof(Robin_Wcf_SvcLib.Service1), new Uri[] { baseAddress }); 

      //服務綁定 

      NetTcpBinding bind 
      = new NetTcpBinding(); 

      host.AddServiceEndpoint(
      typeof(Robin_Wcf_SvcLib.IService1), bind, ""); 

      if (host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>() == null



      System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior 
      = new System.ServiceModel.Description.ServiceMetadataBehavior(); 

      svcMetaBehavior.HttpGetEnabled 
      = true

      svcMetaBehavior.HttpGetUrl 
      = new Uri("http://127.0.0.1:8001/Mex"); 

      host.Description.Behaviors.Add(svcMetaBehavior); 



      host.Opened
      +=new EventHandler(delegate(object obj,EventArgs e){ 

      Console.WriteLine(
      "服務已經啟動!"); 

      }); 

      foreach (var sep in host.Description.Endpoints) 



      sep.Behaviors.Add(
      new RobinLib.OutputMessageBehavior()); 

      foreach (var op in sep.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





      host.Open(); 

      Console.Read(); 







       

       

      2.  在客戶端代理代碼中:

       

       

      代碼
      [System.Diagnostics.DebuggerStepThroughAttribute()] 

      [System.CodeDom.Compiler.GeneratedCodeAttribute(
      "System.ServiceModel""3.0.0.0")] 

      public partial class Service1Client : System.ServiceModel.ClientBase<Robin_Wcf_ClientApp.Robin_Wcf_Formatter_Svc.IService1>, Robin_Wcf_ClientApp.Robin_Wcf_Formatter_Svc.IService1 



       

      public Service1Client() 



      base.Endpoint.Behaviors.Add(new RobinLib.OutputMessageBehavior()); 

      foreach (var op in base.Endpoint.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





       

      public Service1Client(string endpointConfigurationName) : 

      base(endpointConfigurationName) 



      base.Endpoint.Behaviors.Add(new RobinLib.OutputMessageBehavior()); 

      foreach (var op in base.Endpoint.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





       

      public Service1Client(string endpointConfigurationName, string remoteAddress) : 

      base(endpointConfigurationName, remoteAddress) 



      base.Endpoint.Behaviors.Add(new RobinLib.OutputMessageBehavior()); 

      foreach (var op in base.Endpoint.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





       

      public Service1Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 

      base(endpointConfigurationName, remoteAddress) 



      base.Endpoint.Behaviors.Add(new RobinLib.OutputMessageBehavior()); 

      foreach (var op in base.Endpoint.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





       

      public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 

      base(binding, remoteAddress) 



      base.Endpoint.Behaviors.Add(new RobinLib.OutputMessageBehavior()); 

      foreach (var op in base.Endpoint.Contract.Operations) 



      op.Behaviors.Add(
      new RobinLib.Base64BodyBehavior()); 





       

      public string GetData(int value) 



      return base.Channel.GetData(value); 



       

      public Robin_Wcf_ClientApp.Robin_Wcf_Formatter_Svc.CompositeType GetDataUsingDataContract(Robin_Wcf_ClientApp.Robin_Wcf_Formatter_Svc.CompositeType composite) 



      return base.Channel.GetDataUsingDataContract(composite); 





       

       

      最后,我們比較一下記錄到的原始消息和經過Base64 正文消息的對比

       

      客戶端請求原始消息

      客戶端Base64正文后消息:

       

      服務器端原始消息:

       

       

      服務端Base64正文后消息:

       

       

      想要學習WCF的一些基礎知識可以訪問如下鏈接:

       

         

         

      WCF從理論到實踐一:揭開神秘面紗

       

         

      WCF從理論到實踐二:決戰紫禁之巔

       

         

      WCF從理論到實踐三:八號當鋪之黑色契約

       

         

      WCF從理論到實踐四:路在何方

       

         

      WCF從理論到實踐:Binding細解

       

         

      WCF從理論到實踐:WCF架構

       

         

      WCF從理論到實踐:消息交換模式

       

         

      WCF從理論到實踐:事件廣播

       

         

      WCF從理論到實踐:實例模式和對象生命周期

       

         

      WCF從理論到實踐:異常處理

       

         

      WCF從理論到實踐-異步

       

         

      WCF從理論到實踐:事務

       

         

      WCF從理論到實踐:事務投票

       

         

      WCF從理論到實踐(14):WCF解決方案模板

       

         

      WCF從理論到實踐(15):響應變化

       

         

      WCF從理論到實踐(16):操作重載(帶視頻+ppt+源碼)

       

         

      WCF從理論到實踐(17):OO大背離(帶視頻+ppt+源碼)

       

         

      Ajax訪問Xml Web Service的安全問題以及解決方案

       

         

      AjaxWCF交互-WCF之美

       

         

      AjaxWcf交互-JSON

       

         

      ExtJsWCF交互:生成樹

       

         

      ExtJs+Linq+Wcf打造簡單grid

       
       

      ExtJs+WCF+LINQ實現分頁Grid

       

         

      ExtJsWCF之間的跨域訪問

       

         

      異步調用RestfulWCF服務

       

         

      利用WCFRestful進行上傳下載

        

      項目文件: /Files/jillzhang/Robin_Wcf_Formatter.rar

       

      posted @ 2010-04-11 00:11  Robin Zhang  閱讀(5218)  評論(20)    收藏  舉報
      主站蜘蛛池模板: 楚雄市| 人人人爽人人爽人人av| 色偷偷女人的天堂亚洲网| 国产最新进精品视频| 亚洲av中文乱码一区二| 亚洲精品在线少妇内射| 亚洲大尺度一区二区三区| 日本无遮挡吸乳呻吟视频| 男人一天堂精品国产乱码| 闵行区| 午夜三级成人在线观看| 久久久久国产精品人妻| 亚洲成av人片在www色猫咪| 亚洲一久久久久久久久| 牲欲强的熟妇农村老妇女视频| 亚洲成在人天堂一区二区| 116美女极品a级毛片| 99中文字幕国产精品| 蜜桃av色偷偷av老熟女| 在线中文字幕国产精品| 国产精品日韩中文字幕| 日韩女同一区二区三区久久 | 资源在线观看视频一区二区| 四虎国产精品成人免费久久| 亚洲深夜精品在线观看| 偷拍专区一区二区三区| 久热这里只有精品视频3| 波多野结衣久久一区二区| 亚洲天堂男人影院| 伊人成人在线视频免费| 亚洲 欧美 中文 日韩aⅴ| 久久中精品中文字幕入口| 亚洲天堂网色图伦理经典| 亚欧美闷骚院| 久久国内精品一区二区三区| 毛片无遮挡高清免费| 国产普通话对白刺激| 国产亚洲精品超碰热| 久久婷婷国产精品香蕉| 国产女同一区二区在线| 亚洲国产成人综合精品|