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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。