热门:网页模板.net视频教程JQueryMVCjsonExtJs源码示例三级联动JQuery菜单
您现在的位置:.Net中文社区>> Silverlight>>正文内容

详解Silverlight下使用WCF通信

发布时间:2010年04月01日点击数: 佚名

一、简单介绍下WCF

  全名:Windows Communication Foundation 从Dotnet Framework 3.0开始出现,WCF通信提供了用HTTP、TCP和IPC信道进行通信的多个方法。WCF提供的信道使用DCOM进行通信。WCF适合于要独立于平台快速的发送消息。服务提供一个端点,包括三个:合同Contract、绑定Binding和地址Endpoint。合同定义了服务提供的操作(接口及实现),绑定控制协议和编码信息(如SL支持的basicHttpBinding)、地址给出服务的位置(地址及目标名)。WCF支持SOAP(Simple Object Access Protocol)、WSDL(Web Services Description Language)。

二、开始实现在SL下的WCF。
  我们要做一个用户登陆的例子,具体流程为:SL调用WCF服务,服务中通过ADO调用存储过程进行登陆验证,把结果返回到本地SL。
1、首先写一个SQL表:

  1. CREATE TABLE UserInfoTable 
  2.     UserName NVARCHAR(20) PRIMARY KEY
  3.     UserPsw NVARCHAR(15) 

2、写个简单的存储过程:(SQL登陆存储过程)

  1. SET ANSI_NULLS ON 
  2. GO 
  3. SET QUOTED_IDENTIFIER ON 
  4. GO 
  5. -- ============================================= 
  6. -- Author:        寻雨 
  7. -- Create date: 2010-4-1-12:45 
  8. -- Description:    验证用户登陆情况.登陆成功则返回0,登陆失败返回1; 
  9. -- ============================================= 
  10. CREATE PROCEDURE sp_Login 
  11.     @UserNum NVARCHAR(20), 
  12.     @UserPsw NVARCHAR(15) 
  13. AS 
  14. BEGIN 
  15.     IF EXISTS(SELECT * FROM UserInfoTable WHERE UserNum=@UserNum AND UserPsw = @UserPsw) 
  16.         RETURN 0; 
  17.     RETURN 1; 
  18. END 
  19. GO 

3、开始建立WCF服务
1、新建WCF服务
在Web端右键,新建,“启用Silverlight功能的WCF服务”,自己输入一个名字,我这里例子名为DataCmd。可以看到App_Code里多了DataCmd.cs,外面多了DataCmd.svc。打开这个SVC文件我们可以看到:

  1. <%@ ServiceHost Language="C#" Debug="true" Service="DataCmd" CodeBehind="~/App_Code/DataCmd.cs" %> 

只有一行,Service指服务类的全名,就是在代码文件中被标记为[ServiceContract]的类(称为服务合同),CodeBehind指的是服务类的代码文件。此地要注意,服务类的代码文件放入App_Code,但SVC绝对不可以放入App_Code,否则会造成403无法访问的错误,因为App_Code自动编译,为了代码安全外面无法访问。

2、实现服务合同
在App_Code里新建一个接口,取名IDataCmd.cs,具体代码如下:注意命名空间

  1. using System.ServiceModel; 
  2.  
  3. /// <summary> 
  4. /// DataCmd.svc的服务合同接口. 
  5. /// </summary> 
  6.  
  7. [ServiceContract] 
  8. public interface IDataCmd 
  9.     /// <summary> 
  10.     /// 验证登陆 
  11.     /// </summary> 
  12.     [OperationContract] 
  13.     bool LoginByUserInfo(string userNum, string userPsw); 
  14.  
  15.     /// <summary> 
  16.     /// 插入新用户 
  17.     /// </summary> 
  18.     [OperationContract] 
  19.     bool RegNewUser(string userNum, string userPsw, string realName, string className, string phone); 

服务合同类中存放服务的实现,一般建议将所有的服务函数写成一个接口。因此我们除了一开始自动生成的服务合同类DataCmd.cs外,创建了IDataCmd.cs的接口。这样我们只用在接口中标记[ServiceContract]和[OperationContract]。用户也可以按生成的DataCmd.cs的样式写服务合同类,只不过用接口会方便一些而已。在改写DataCmd.cs前,我先介绍一下我写的SqlAdapt,是一个简单的Sql访问类,访问数据库时会用到,其他的不多说了,SqlAdapt代码如下:

  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Web; 
  5. using System.Data.SqlClient; 
  6. using System.Data; 
  7.  
  8. /// <summary> 
  9. /// 用于处理Sql通信 请在Using语句块中使用.类会自动关闭连接.否则需要主动调用Close(); 仅单线程安全. 
  10. /// </summary> 
  11. public class SqlAdapt : IDisposable 
  12.     private SqlConnection SqlConn; 
  13.     private SqlCommand SqlComm; 
  14.  
  15.     public SqlAdapt(string SqlConnKey) 
  16.     { 
  17.         try 
  18.         { 
  19.             SqlConn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings[SqlConnKey].ToString()); 
  20.         } 
  21.         catch 
  22.         { 
  23.             try 
  24.             { 
  25.                 SqlConn = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings[SqlConnKey].ToString()); 
  26.             } 
  27.             catch 
  28.             { 
  29.                 throw new Exception("The SqlConnKey Is Wrong!"); 
  30.             } 
  31.         } 
  32.         SqlConn.Open(); 
  33.         SqlComm = SqlConn.CreateCommand(); 
  34.     } 
  35.  
  36.     public int ExecuteNonQuery(string tSql) 
  37.     { 
  38.         SqlComm.CommandType = CommandType.Text; 
  39.         SqlComm.CommandText = tSql; 
  40.         return SqlComm.ExecuteNonQuery(); 
  41.     } 
  42.  
  43.     public void AddParams(SqlParameter sqlParam) 
  44.     { 
  45.         SqlComm.Parameters.Add(sqlParam); 
  46.     } 
  47.  
  48.     public void AddParams(string ParamName, object Params, SqlDbType SqlType, int Size, ParameterDirection PD) 
  49.     { 
  50.         SqlParameter sqlParam = new SqlParameter(ParamName, Params); 
  51.         sqlParam.SqlDbType = SqlType; 
  52.         sqlParam.Size = Size; 
  53.         sqlParam.Direction = PD; 
  54.         SqlComm.Parameters.Add(sqlParam); 
  55.     } 
  56.  
  57.     public void AddParams(string ParamName, object Params, SqlDbType SqlType , ParameterDirection PD) 
  58.     { 
  59.         SqlParameter sqlParam = new SqlParameter(ParamName, Params); 
  60.         sqlParam.SqlDbType = SqlType; 
  61.         sqlParam.Direction = PD; 
  62.         SqlComm.Parameters.Add(sqlParam); 
  63.     } 
  64.  
  65.  
  66.     public object ExecuteProcedure(string pSql) 
  67.     { 
  68.         SqlComm.CommandType = CommandType.StoredProcedure; 
  69.         SqlComm.CommandText = pSql; 
  70.         SqlComm.Parameters.Add(new SqlParameter("@RETURN_VALUE""")).Direction = ParameterDirection.ReturnValue; 
  71.         SqlComm.ExecuteNonQuery(); 
  72.         return SqlComm.Parameters["@RETURN_VALUE"].Value; 
  73.     } 
  74.  
  75.     public void ExecProc(string pSql) 
  76.     { 
  77.         SqlComm.CommandType = CommandType.StoredProcedure; 
  78.         SqlComm.CommandText = pSql; 
  79.         SqlComm.ExecuteNonQuery(); 
  80.     } 
  81.  
  82.     public void Close() 
  83.     { 
  84.         SqlComm.Parameters.Clear(); 
  85.         if (SqlConn.State != ConnectionState.Closed) 
  86.         { 
  87.             SqlConn.Close(); 
  88.         } 
  89.     } 
  90.  
  91.     public SqlParameter GetParam(string paramName) 
  92.     { 
  93.         return SqlComm.Parameters[paramName]; 
  94.     } 
  95.  
  96.     public SqlParameterCollection GetParamCollection { getset; } 
  97.  
  98.     public void Dispose() 
  99.     { 
  100.         SqlComm.Parameters.Clear(); 
  101.         if (SqlConn.State != ConnectionState.Closed) 
  102.         { 
  103.             SqlConn.Close(); 
  104.         } 
  105.     } 

下面是我改写后的DataCmd.cs,实现了IDataCmd接口。对SQL访问请参照上面的代码。

  1. using System; 
  2. using System.Linq; 
  3. using System.Runtime.Serialization; 
  4. using System.ServiceModel; 
  5. using System.ServiceModel.Activation; 
  6. using System.Collections.Generic; 
  7. using System.Text; 
  8. using System.Data; 
  9.  
  10. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
  11. public class DataCmd : IDataCmd 
  12.  
  13.     #region IDataCmd 成员 
  14.  
  15.     public bool LoginByUserInfo(string userNum, string userPsw) 
  16.     { 
  17.         using (SqlAdapt sql = new SqlAdapt("SqlConnectionString")) 
  18.         { 
  19.             sql.AddParams("@UserNum", userNum, SqlDbType.NVarChar, 20, ParameterDirection.Input); 
  20.             sql.AddParams("@UserPsw", userPsw, SqlDbType.NVarChar, 15, ParameterDirection.Input); 
  21.             return (int)sql.ExecuteProcedure("sp_Login")==0?true:false
  22.         } 
  23.     } 
  24.  
  25.     public bool RegNewUser(string userNum, string userPsw, string realName, string className, string phone) 
  26.     { 
  27.         throw new NotImplementedException(); 
  28.     } 
  29.  
  30.     #endregion 

一切都完成后,我们可以执行下这个svc。如果没有意外,会显示已创建服务,并让你测试。这里可以用命令行测试下自己的数据库存取是否正确。

3、下面为大家讲解下基于SL的WCF简单配置。打开Web.Config后,我取出与WCF有关的部分(ServiceModel结点),在这里我就不罗列系统默认的配置了,只列出我自己的配置来与大家一起分析。

  1. <system.serviceModel> 
  2.  这是第一部分:配置行为 
  3.    <behaviors> 
  4.     <serviceBehaviors> 
  5.   
  6.      <behavior name="DataCmdBehavior 行为配置的ID"> 
  7.       <serviceMetadata httpGetEnabled="true" /> 
  8.       <serviceDebug includeExceptionDetailInFaults="false" /> 
  9.      </behavior> 
  10.   
  11.     </serviceBehaviors> 
  12.    </behaviors> 
  13.  这是第二部分:配置绑定 
  14.      <bindings> 
  15.         <basicHttpBinding> 
  16.            <binding name="bHttpBind 绑定配置的ID">    
  17.               <readerQuotas />  这些都可以根据情况增加参数 
  18.               <security> 
  19.                  <transport> 
  20.                     <extendedProtectionPolicy policyEnforcement="Never" /> 
  21.                  </transport> 
  22.               </security> 
  23.            </binding> 
  24.         </basicHttpBinding> 
  25.      </bindings> 
  26.  这是第三部分:配置服务 
  27.    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
  28.    <services> 
  29.   
  30.     <service behaviorConfiguration="DataCmdBehavior 写行为配置ID" name="DataCmd 服务合同类"> 
  31.      <endpoint address="" binding="basicHttpBinding" bindingConfiguration="bHttpBind 写端口配置的ID" 
  32.       contract="IDataCmd 服务合同接口" /> 
  33.     </service> 
  34.   
  35.    </services> 
  36.   </system.serviceModel> 

从代码可以看出,前两部分是为第三部分做准备的。如果要配置多个WCF只用多增加结点就可以了。

4、 SL端的配置
接下来要配置客户端的东西了,在SL项目中的引用,右键“添加服务引用”,之后点发现,找到我们刚创建的服务,添加进来就可以。当然,要写好命名空间。
之后会生成一个叫“Service References ”的文件夹,在里面可以看到刚添加的服务,双击可以打开对象管理器,看到它所有的成员。
下面我来写客户端,当单击一个按扭时,以TextBox和PasswordBox中数据为用户和密码,调用WCF服务,进行验证。并针对结果,用MessageBox给出不同的对话框。代码如下:

  1. private void Log_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
  2.         { 
  3.             //进行登陆 
  4.                 DataCmdClient dcClient = new DataCmdClient(); 
  5.                 dcClient.LoginByUserInfoCompleted += new EventHandler<LoginByUserInfoCompletedEventArgs>(dcClient_LoginByUserInfoCompleted); 
  6.                 dcClient.LoginByUserInfoAsync(UserNameBox.Text, PasswordBox.Password); 
  7.         } 
  8.  
  9.         void dcClient_LoginByUserInfoCompleted(object sender, LoginByUserInfoCompletedEventArgs e) 
  10.         { 
  11.             if (e.Result) 
  12.             { 
  13.                 MessageBox.Show("GOOD Login"); 
  14.             } 
  15.             else 
  16.             { 
  17.                 MessageBox.Show("Bad Can't In"); 
  18.             } 
  19.         } 

到这里,整个例子就讲完了。希望这篇文章对大家有所帮助。

本站热点业务

更多模板/案例展示

关于我们 | 联系我们 | 团队日志 | 网站地图 | 网站合作