WCF初探-16:WCF数据协定之基础知识
WCF初探-19:WCF消息协定
public Message GetDataEmpty() { MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataEmptyResponse"); }
public Message GetDataObject() { User user = new User(); user.Name = "JACK"; user.Age = 20; user.ID = 1; user.Nationality = "CHINA"; MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataObjectResponse", user); }
示例代码如下:
public Message GetDataXml() { string path = Environment.CurrentDirectory.Substring(0, Environment.CurrentDirectory.IndexOf("bin")) + "test.xml"; FileStream stream = new FileStream(path, FileMode.Open); XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataXmlResponse", xdr); }
public Message GetDataFault() { FaultException<FaultMessage> fe = new FaultException<FaultMessage> (new FaultMessage("错误时间:" + System.DateTime.Now.ToString(), "输入的字符串大于10个字符")); MessageFault fault = fe.CreateMessageFault(); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, fault, "http://tempuri.org/IUserInfo/GetDataFaultResponse"); }
using System.ServiceModel; using System.Runtime.Serialization; using System.ServiceModel.Channels; namespace Service { [ServiceContract] public interface IUserInfo { [OperationContract] Message GetDataEmpty(); [OperationContract] Message GetDataObject(); [OperationContract] Message GetDataXml(); [OperationContract] Message GetDataFault(); } [MessageContract] public class User { [MessageBodyMember] public int ID { get; set; } [MessageBodyMember] public string Name { get; set; } [MessageBodyMember] public int Age { get; set; } [MessageBodyMember] public string Nationality { get; set; } } [DataContract] public class FaultMessage { private string _errorTime; private string _errorMessage; [DataMember] public string ErrorTime { get { return this._errorTime; } set { this._errorTime = value; } } [DataMember] public string ErrorMessage { get { return this._errorMessage; } set { this._errorMessage = value; } } public FaultMessage(string time, string message) { this._errorTime = time; this._errorMessage = message; } } }
UserInfo.cs的代码如下:
using System.ServiceModel.Channels; using System.ServiceModel; using System.IO; using System; using System.Xml; namespace Service { public class UserInfo:IUserInfo { public Message GetDataEmpty() { MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataEmptyResponse"); } public Message GetDataObject() { User user = new User(); user.Name = "JACK"; user.Age = 20; user.ID = 1; user.Nationality = "CHINA"; MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataObjectResponse", user); } public Message GetDataXml() { string path = Environment.CurrentDirectory.Substring(0, Environment.CurrentDirectory.IndexOf("bin")) + "test.xml"; FileStream stream = new FileStream(path, FileMode.Open); XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://tempuri.org/IUserInfo/GetDataXmlResponse", xdr); } public Message GetDataFault() { FaultException<FaultMessage> fe = new FaultException<FaultMessage> (new FaultMessage("错误时间:" + System.DateTime.Now.ToString(), "输入的字符串大于10个字符")); MessageFault fault = fe.CreateMessageFault(); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, fault, "http://tempuri.org/IUserInfo/GetDataFaultResponse"); } } }
2. Host:控制台应用程序,服务承载程序。添加对程序集Service的引用,完成以下代码,寄宿服务。Program.cs代码如下:
logs_code_hide('9c21ea35-7f8b-4301-9cbc-5dd58cc90ca8',event)" src="/Upload/Images/2015050810/2B1B950FA3DF188F.gif" alt="" />using System; using System.ServiceModel; using Service; namespace Host { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(UserInfo))) { host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); }; host.Open(); Console.Read(); } } } }View Code
由于wsHttpBinding默认启用安全机制,为了简便的观察消息体结构,在本示例中设置wsHttpBinding的security mode="None",App.config的代码如下:
<?xml version="1.0"?> <configuration> <system.serviceModel> <services> <service name="Service.UserInfo" behaviorConfiguration="mexBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:1234/UserInfo/"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="Service.IUserInfo" bindingConfiguration="bindConfig"/> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="mexBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <wsHttpBinding> <binding name="bindConfig"> <security mode="None" /> </binding> </wsHttpBinding> </bindings> </system.serviceModel> <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
test.xml文件的内容如下:
<?xml version="1.0" encoding="utf-8" ?> <User> <ID>1</ID> <Name>20</Name> <Age>JACK</Age> <Nationality>CHINA</Nationality> </User>
运行Host.exe程序,成功寄宿服务后,我们通过svcutil.exe工具生成客户端代理类和客户端的配置文件svcutil.exe是一个命令行工具,
位于路径C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin下,我们可以通过命令行运行该工具生成客户端代理类
3. Client:控制台应用程序,客户端调用程序。将生成的UserInfoClient.cs和App.config复制到Client的工程目录下,完成客户端调用代码。Program.cs的代码如下:
using System; using System.ServiceModel.Channels; namespace Client { class Program { static void Main(string[] args) { UserInfoClient proxy = new UserInfoClient(); //显示创建基本消息(空消息) //Message message = proxy.GetDataEmpty(); //Console.WriteLine(message.ToString()); //显示从对象创建消息 //Message message = proxy.GetDataObject(); //Console.WriteLine(message.ToString()); //显示从XML读取器创建消息 //Message message = proxy.GetDataXml(); //Console.WriteLine(message.ToString()); //显示创建错误消息 Message message = proxy.GetDataFault(); Console.WriteLine(message.ToString()); Console.Read(); } } }
从运行结果可以看出一个基本的消息结构为<s:Envelope></ s:Envelope >,其中包含消息头<s:Header>< s:Header >和消息正文<s:Body></ s:Body >
从运行结果可以看出类型为User的MessageContract转化为了消息的正文部分
从运行结果可以看出读取文件test.xml的内容转化为了消息正文部分
从运行结果可以看出类型为FaultMessage的DataContract转化为了消息的正文部分,并且嵌套在了错误消息结构<s:Fault>下的<s:Detail>中。