WCF应用(二)
WCF串说
1、通过在上一篇博客中我们建立第一个自宿主的wcf服务,我们基本上了解了Wcf的作用以及wcf的基本建立方式。我的上一篇博文链接: WCF应用(一)
2、这篇博文我就通过建立wcf的另一种宿主方式,iis宿主服务,对wcf的数据契约,操作契约,错误契约做个了解应用。
创建wcf的iis宿主服务
创建第一步:在解决方案中添加新建项目IISserver
创建第二步:在添加的新建项目IISserver中客户端要调用的方法
IService1.cs中代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
namespace IISserver { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 [ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); [OperationContract] //定义为操作契约 int sum(int i,int j); // TODO: 在此添加您的服务操作 } // 使用下面示例中说明的数据约定将复合类型添加到服务操作。 [DataContract] public class CompositeType { bool boolValue = true; string stringValue = "Hello "; [DataMember] public bool BoolValue { get { return boolValue; } set { boolValue = value; } } [DataMember] public string StringValue { get { return stringValue; } set { stringValue = value; } } } }
Service1.svc中代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
namespace IISserver { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。 public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite == null) { throw new ArgumentNullException("composite"); } if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } //实现接口层中写入的方法签名 public int sum(int i, int j) { return i + j; } } }
创建第三步:创建客户端的应用程序,c#语言可以为控制台程序,web应用程序,winForm应用程序。上一篇博文中穿件的是WinForm程序,这一篇我创建一个Web应用程序。
1、运行创建的iis宿主服务的Service1.svc文件,右键点击文件在浏览器中查看即可。复制运行后的地址。
2、在创建的应用程序中,添加服务引用,在出现的对话框中,要求输地址的框中粘帖上复制过的地址。点击前往,等发现服务后,点击确定即可。
在创建的web应用程序中使用服务。代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; //注意这里添加的引用 using WCFUsing.IIsServiceReference; namespace WCFUsing { public partial class WCFusing : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //在客户端实例化服务端可操作的类 Service1Client Server1 = new Service1Client(); //使用刚才自己写在服务端的sum方法 string sumReslut =Server1.sum(1,2).ToString(); Response.Write(sumReslut); } } }
这时候你点击运行页面,页面运行结果就出现了。
注意:
1、我这里没有部署到iis上,使用的是微软提供的模拟的iis服务器(ASP.NET Development server),这个服务器是本地测试用的,使用的时候端口不一定,所以链接wcf服务的时候要检查更新服务引用中的地址。
2、由于使用的是微软提供的本地web服务,所以我们每次使用wcf服务的时候还要注意先运行创建iis宿主服务项目中的sav文件。
3、如果你在服务端更改或添加了方法。那么你就要在客户端右键你添加的服务应用,然后更新。
了解使用数据契约
WCF数据契约(Data Contract)是用来标识用户自定义类型和序列化。DataContractAttribute、 DataMemberAttribute 来标注自定义数据类型,这样我们就可以在服务方法中传递复杂的数据体了。
1、创建一个Person类,注意添加应用using System.Runtime.Serialization;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
namespace IISserver { [DataContract]//数据契约属性声明 public class Person { [DataMember(Name = "myName")]//数据成员标记,支持别名定义 public string Name { get; set; } [DataMember(Name="myAge")] public int Age { get; set; } //方法不能被放在数据契约里面,否则编译失败。 //[DataMember] //public string SayHello(string name,int age) //{ // return name + ":你好,你明年" + (age + 1).ToString() + "岁!"; //} } }
2、写一个方法给Person类中的属性赋值,由于方法不能直接定义在数据契约中,只能定义在服务契约和操作契约中。所以在IService1.cs中添加方法代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); [OperationContract] //定义为操作契约 int sum(int i,int j); [OperationContract] //定义为操作契约 Person SetPerson(Person p); // TODO: 在此添加您的服务操作 }
3、 Service1.svc中实现方法代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
namespace IISserver { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。 public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite == null) { throw new ArgumentNullException("composite"); } if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } //实现接口层中写入的方法签名 public int sum(int i, int j) { return i + j; } //设置数据契约中Person类中属性的值 public Person SetPerson(Person p) { p.Name = "小"; p.Age = 3; return p; } } }
4、在重新运行svc文件,在客户端更新服务引用。应用程序中写代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System.Web.UI.WebControls; //注意这里添加的引用 using WCFUsing.IIsServiceReference; namespace WCFUsing { public partial class WCFusing : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //在客户端实例化服务端可操作的类 Service1Client Server1 = new Service1Client(); //定义为数据契约,这里就能访问到了 Person p = new Person(); p.myAge = 10; p.myName = "Tom"; //注意这里的p已经是在服务端更新过的。 p=Server1.SetPerson(p); Response.Write(p.myName+p.myAge); //显示结果是“小三” } } }
附带说明:在定义表示为数据契约的时候有以下属性:
DataContract 的属性
Name / Namespace:自定义名称和命名空间。
DataMember 的属性
Name:自定义名称。
IsRequired:指示该成员序列化前必须被赋值。
了解使用wcf错误契约
在默认情况下,服务抛出的异常均以FaultException类型传递到客户端。原因在于任何服务希望与客户端共享的基于通信错误之上的任何异常,都必 须属于服务契约行为的一部分。为此,WCF提供了错误契约,通过它列出服务能够抛出的错误类型。这些错误类型应该与 FaultException<T>使用的类型参数的类型相同。只要它们在错误契约中列出,WCF客户端就能够分辨契约错误与其他错误之间的区别。
IService1.cs中代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[OperationContract] //定义为操作契约 [FaultContract(typeof(Exception))] //定义为错误契约 int sum(int i,int j);
Service1.svc中代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//实现接口层中写入的方法签名 public int sum(int i, int j) { if (j == 0) { Exception er = new Exception(); throw new FaultException<Exception>(er, "除数不能为0"); } else { return i / j; } }
Web应用程序中的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
protected void Page_Load(object sender, EventArgs e) { try { Service1Client Server1 = new Service1Client(); Response.Write(Server1.sum(0,0)); //这里设置的为能引发异常的参数 } catch (Exception ex) { Response.Write(ex.Message); //输出异常信息,输出“除数不能为零” } }
小结:这样,你应该也对wcf的应用又有了个进一步的了解吧。呵呵。