WCF閑談:如何在流模式下傳遞參數
正好在園子中看到一篇博文在流模式下保持服務實例的狀態的兩種設計方式,細心的看了看,發現博主對WCF下流傳輸做了很深入的研究,但在程序的實現上頗顯復雜,沒有充分并且靈活的運用WCF的特性,在博主的那篇文章中要實現的目的就是將本地一個文件用流形式傳遞給遠程,并且要求遠程和本地的文件名稱一致。樓主的實現中,在PerCall模式下一次調用完不成一次傳輸,需要在調用的過程中,用靜態變量保持會話,這樣顯然過于復雜。其實這個實現非常簡單,只需要運用MessageHeader就能輕松解決,我前面的文章WCF 進階:為每個操作附加身份信息中也提到了,使用MessageHeader能附加用戶身份信息,那么附件任何其他信息,行不行,肯定是沒問題的。所以。。。。
服務:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.IO; namespace Robin_Wcf_Stream_SvcLib { // 注意: 如果更改此處的類名“IService1”,也必須更新 App.config 中對“IService1”的引用。 public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } public string StreamOperation(Stream stream) { System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("utf-8"); string name = ""; int index = OperationContext.Current.IncomingMessageHeaders.FindHeader("filename", "http://tempuri.org"); if (index >= 0) { name = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index).ToString(); } byte[] buffer = RetrieveBytesFromStream(stream); string text = System.Text.Encoding.UTF8.GetString(buffer); Console.WriteLine("哈哈哈,我已經收到文件名稱:"+name+",并且字節流中的數據為:"+text); return name; } public static byte[] RetrieveBytesFromStream(Stream stream) { List<byte> lst = new List<byte>(); byte[] data = new byte[1024]; int totalCount = 0; while (true) { int bytesRead = stream.Read(data, 0, data.Length); if (bytesRead == 0) { break; } byte[] buffers = new byte[bytesRead]; Array.Copy(data, buffers, bytesRead); lst.AddRange(buffers); totalCount += bytesRead; } return lst.ToArray(); } } }
宿主:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using Robin_Wcf_Stream_SvcLib; namespace Robin_Wcf_Stream_Host { class Program { static void Main(string[] args) { //服務地址 Uri baseAddress = new Uri("http://127.0.0.1:8081/"); ServiceHost host = new ServiceHost(typeof(Service1), new Uri[] { baseAddress }); //服務綁定 BasicHttpBinding bind = new BasicHttpBinding(); host.AddServiceEndpoint(typeof(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("服務已經啟動!"); }); host.Open(); Console.Read(); } } }
客戶端:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Robin_Wcf_Stream_Client.ServiceReference1; using System.ServiceModel; using System.ServiceModel.Channels; namespace Robin_Wcf_Stream_Client { class Program { static void Main(string[] args) { System.Threading.Thread.Sleep(4000); Service1Client svc = new Service1Client(); using (OperationContextScope scope = new OperationContextScope(svc.InnerChannel)) { MessageHeader header = MessageHeader.CreateHeader("filename", "http://tempuri.org", "robinzhang"); OperationContext.Current.OutgoingMessageHeaders.Add(header); System.IO.MemoryStream ms = new System.IO.MemoryStream(); byte[] buffer = System.Text.Encoding.UTF8.GetBytes("您好,尊敬的用戶!"); ms.Write(buffer, 0, buffer.Length); ms.Seek(0, System.IO.SeekOrigin.Begin); string res = svc.StreamOperation(ms); Console.WriteLine(res); Console.Read(); } } } }
一次調用搞定!
效果圖如下:
服務端:
客戶端:
項目文件:點擊下載
作者:jillzhang
出處:http://jillzhang.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
出處:http://jillzhang.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

浙公網安備 33010602011771號