之前很经常听说WCF,不过没有怎么接触过,直到最近才真正使用到WCF,虽然也只是皮毛而已,在此也做个记录总结吧。
下图是我使用WCF的练手项目,由于是使用VS2010直接创建的WCF服务应用程序,VS已经自动搭建好了简单的服务,暂时不用配置复杂的Web.config。项目的基本结构比较简单,如下所示:
Contracts文件夹中存放的是服务契约,也就是对暴露给客户端的方法接口。
Model文件夹中存放的是数据契约,是自定义的实体类。
Service文件夹中存放的是对服务契约所实现的方法。
其中服务契约的写法跟普通的接口写法基本一样,只是在接口上添加了[ServiceContract]特性,并且每个操作方法都要添加[OperationContract]特性而已
1 using System.ServiceModel; 2 using OrderingWCFService.Model; 3 using System.Collections.Generic; 4 5 namespace OrderingWCFService.Contracts 6 { 7 [ServiceContract] 8 public interface IFoodKindServer 9 { 10 /// <summary> 11 /// 获取全部的食品种类信息 12 /// </summary> 13 /// <returns>全部的食品种类集合</returns> 14 [OperationContract] 15 IList<FoodKind> GetAllFoodKinds(); 16 } 17 }
数据契约的写法也差不多,在实体类上添加[DataContract]特性,并且每个属性也要写上[DataMember(Name = "KindID", IsRequired = false, Order = 0)]这样的特性,
其中Name表示的是别名,IsRequired则表示该属性在序列化之后该属性是否必须存在,而Order则表示的是序列化之后的显示顺序。
1 using System.Runtime.Serialization; 2 3 namespace OrderingWCFService.Model 4 { 5 [DataContract] 6 public class FoodKind 7 { 8 /// <summary> 9 /// 种类ID 10 /// </summary> 11 [DataMember(Name = "KindID", IsRequired = false, Order = 0)] 12 public int KindID { get; set; } 13 14 /// <summary> 15 /// 种类名称 16 /// </summary> 17 [DataMember(Name = "KindName", IsRequired = false, Order = 1)] 18 public string KindName { get; set; } 19 20 /// <summary> 21 /// 父种类 22 /// </summary> 23 [DataMember(Name = "Parent", IsRequired = false, Order = 2)] 24 public FoodKind Parent { get; set; } 25 } 26 }
服务的实现中不需要写什么标记,只需要实现接口就行了
1 using OrderingWCFService.Contracts; 2 using OrderingWCFService.Model; 3 using System.Data.Odbc; 4 using System.Data; 5 using System; 6 7 namespace OrderingWCFService 8 { 9 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service”。 10 public partial class Service 11 { 12 } 13 }
由于为了不让所有的服务实现都显示在Service.svc这个文件中,也为了更好的管理代码,我使用了分部类
1 using System; 2 using System.Data.Odbc; 3 using System.Data; 4 using OrderingWCFService.Contracts; 5 using OrderingWCFService.Model; 6 using System.Collections.Generic; 7 8 namespace OrderingWCFService 9 { 10 public partial class Service : IFoodKindServer 11 { 12 public FoodKind GetFoodKindByKindID(int KindID) 13 { 14 try 15 { 16 using (OdbcDataReader dr = OracleHelper.ExecuteReader("select * from tb_foodKind where KindID=?", new OdbcParameter("@KindID", KindID))) 17 { 18 if (dr.Read()) 19 { 20 FoodKind kind = new FoodKind(); 21 kind.KindID = Int32.Parse(dr["KindID"].ToString()); 22 kind.KindName = dr["KindName"].ToString(); 23 //判断父种类ID是否不为空 24 if (dr["ParentID"]!=DBNull.Value) 25 { 26 kind.Parent = GetFoodKindByKindID(Int32.Parse(dr["ParentID"].ToString())); 27 } 28 else 29 { 30 kind.Parent = null; 31 } 32 return kind; 33 } 34 return null; 35 } 36 } 37 catch (Exception) 38 { 39 return null; 40 } 41 } 42 43 public IList<FoodKind> GetAllFoodKind() 44 { 45 try 46 { 47 DataSet ds = OracleHelper.Query("select * from tb_foodKind"); 48 DataTable dt = ds.Tables[0]; 49 IList<FoodKind> lst = new List<FoodKind>(); 50 foreach (DataRow dr in dt.Rows) 51 { 52 FoodKind kind = new FoodKind(); 53 kind.KindID = Int32.Parse(dr["KindID"].ToString()); 54 kind.KindName = dr["KindName"].ToString(); 55 if (dr["ParentID"] != DBNull.Value) 56 { 57 kind.Parent = GetFoodKindByKindID(Int32.Parse(dr["ParentID"].ToString())); 58 } 59 else 60 { 61 kind.Parent = null; 62 } 63 lst.Add(kind); 64 } 65 return lst; 66 } 67 catch (Exception) 68 { 69 return null; 70 } 71 } 72 } 73 }
好了,自此位置WCF基本的用法已经熟悉了,然后就可以搭建WCF服务了。
首先就是发布WCF服务,选择发布
然后选择文件系统跟存放路径,按发布
发布成功之后D:\OrderingWCFService就会有这些文件了
然后就可以使用IIS发布WCF服务了,选择刚才的文件夹进行发布
注意IP地址记得要选择详细的IP地址,而且系统防火墙跟自己安装的软件防火墙要关闭之后别人才能访问到IIS发布的服务,之前我就是由于这两个问题坑了很久。
确定之后还要把目录浏览启用
然后就可以浏览WCF服务了,单击Service.svc就可以启用服务了
服务启动后,就可以在客户端引用服务进行调用了,右键客户端项目添加服务引用:
在地址中输入WCF的服务地址,单价前往进行搜索
然后修改命名空间的名字,单击确认就可以添加引用了,最后只要对其进行调用就可以了
1 public void WCFTest() 2 { 3 using (WCF.FoodKindServerClient target=new WCF.FoodKindServerClient ()) 4 { 5 IList<FoodKind> lst =target.GetAllFoodKind(); 6 } 7 }
WCF就是刚才引用服务时创建的命名空间,FoodKindServerClient则是实现了IFoodKind接口的客户端代理,使用该代理可以直接调用IFoodKind接口的操作方法。
自此,使用WCF的流程就演示完毕了,最后提示一下,如果WCF服务更新了,只需要对服务右键选择更新服务引用就可以对服务进行更新了。
WCF的学习就到此为止了,以后如果有新的知识再对其进行补充。