在Silverlight下使用WCF通信.

关于在SL下实现WCF通信的文章很多,因此我着重从我的实践上讲解,这样可能易懂一些。

一、简单介绍下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表:

CREATE   TABLE  UserInfoTable
(
    UserName 
NVARCHAR ( 20 PRIMARY   KEY ,
    UserPsw 
NVARCHAR ( 15 )
)

 

2、写个简单的存储过程:

SQL登陆存储过程
SET  ANSI_NULLS  ON
GO
SET  QUOTED_IDENTIFIER  ON
GO
--  =============================================
--
 Author:        寻雨
--
 Create date: 2010-4-1-12:45
--
 Description:    验证用户登陆情况.登陆成功则返回0,登陆失败返回1;
--
 =============================================
CREATE   PROCEDURE  sp_Login
    
@UserNum   NVARCHAR ( 20 ),
    
@UserPsw   NVARCHAR ( 15 )
AS
BEGIN
    
IF   EXISTS ( SELECT   *   FROM  UserInfoTable  WHERE  UserNum = @UserNum   AND  UserPsw  =   @UserPsw )
        
RETURN   0 ;
    
RETURN   1 ;
END
GO

 

3、开始建立WCF服务

1、新建WCF服务

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

<% @ 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,具体代码如下:注意命名空间

代码
using  System.ServiceModel;

///   <summary>
///  DataCmd.svc的服务合同接口.
///   </summary>

[ServiceContract]
public   interface  IDataCmd
{
    
///   <summary>
    
///  验证登陆
    
///   </summary>
    [OperationContract]
    
bool  LoginByUserInfo( string  userNum,  string  userPsw);

    
///   <summary>
    
///  插入新用户
    
///   </summary>
    [OperationContract]
    
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代码如下:

代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Data.SqlClient;
using  System.Data;

///   <summary>
///  用于处理Sql通信 请在Using语句块中使用.类会自动关闭连接.否则需要主动调用Close(); 仅单线程安全.
///   </summary>
public   class  SqlAdapt : IDisposable
{
    
private  SqlConnection SqlConn;
    
private  SqlCommand SqlComm;

    
public  SqlAdapt( string  SqlConnKey)
    {
        
try
        {
            SqlConn 
=   new  SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings[SqlConnKey].ToString());
        }
        
catch
        {
            
try
            {
                SqlConn 
=   new  SqlConnection(System.Configuration.ConfigurationManager.AppSettings[SqlConnKey].ToString());
            }
            
catch
            {
                
throw   new  Exception( " The SqlConnKey Is Wrong! " );
            }
        }
        SqlConn.Open();
        SqlComm 
=  SqlConn.CreateCommand();
    }

    
public   int  ExecuteNonQuery( string  tSql)
    {
        SqlComm.CommandType 
=  CommandType.Text;
        SqlComm.CommandText 
=  tSql;
        
return  SqlComm.ExecuteNonQuery();
    }

    
public   void  AddParams(SqlParameter sqlParam)
    {
        SqlComm.Parameters.Add(sqlParam);
    }

    
public   void  AddParams( string  ParamName,  object  Params, SqlDbType SqlType,  int  Size, ParameterDirection PD)
    {
        SqlParameter sqlParam 
=   new  SqlParameter(ParamName, Params);
        sqlParam.SqlDbType 
=  SqlType;
        sqlParam.Size 
=  Size;
        sqlParam.Direction 
=  PD;
        SqlComm.Parameters.Add(sqlParam);
    }

    
public   void  AddParams( string  ParamName,  object  Params, SqlDbType SqlType , ParameterDirection PD)
    {
        SqlParameter sqlParam 
=   new  SqlParameter(ParamName, Params);
        sqlParam.SqlDbType 
=  SqlType;
        sqlParam.Direction 
=  PD;
        SqlComm.Parameters.Add(sqlParam);
    }


    
public   object  ExecuteProcedure( string  pSql)
    {
        SqlComm.CommandType 
=  CommandType.StoredProcedure;
        SqlComm.CommandText 
=  pSql;
        SqlComm.Parameters.Add(
new  SqlParameter( " @RETURN_VALUE " "" )).Direction  =  ParameterDirection.ReturnValue;
        SqlComm.ExecuteNonQuery();
        
return  SqlComm.Parameters[ " @RETURN_VALUE " ].Value;
    }

    
public   void  ExecProc( string  pSql)
    {
        SqlComm.CommandType 
=  CommandType.StoredProcedure;
        SqlComm.CommandText 
=  pSql;
        SqlComm.ExecuteNonQuery();
    }

    
public   void  Close()
    {
        SqlComm.Parameters.Clear();
        
if  (SqlConn.State  !=  ConnectionState.Closed)
        {
            SqlConn.Close();
        }
    }

    
public  SqlParameter GetParam( string  paramName)
    {
        
return  SqlComm.Parameters[paramName];
    }

    
public  SqlParameterCollection GetParamCollection {  get set ; }

    
public   void  Dispose()
    {
        SqlComm.Parameters.Clear();
        
if  (SqlConn.State  !=  ConnectionState.Closed)
        {
            SqlConn.Close();
        }
    }
}
 

 

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

 

 

代码
using  System;
using  System.Linq;
using  System.Runtime.Serialization;
using  System.ServiceModel;
using  System.ServiceModel.Activation;
using  System.Collections.Generic;
using  System.Text;
using  System.Data;

[AspNetCompatibilityRequirements(RequirementsMode 
=  AspNetCompatibilityRequirementsMode.Allowed)]
public   class  DataCmd : IDataCmd
{

    
#region  IDataCmd 成员

    
public   bool  LoginByUserInfo( string  userNum,  string  userPsw)
    {
        
using  (SqlAdapt sql  =   new  SqlAdapt( " SqlConnectionString " ))
        {
            sql.AddParams(
" @UserNum " , userNum, SqlDbType.NVarChar,  20 , ParameterDirection.Input);
            sql.AddParams(
" @UserPsw " , userPsw, SqlDbType.NVarChar,  15 , ParameterDirection.Input);
            
return (int)sql.ExecuteProcedure("sp_Login")==0?true:false;
        }
    }

    
public   bool  RegNewUser( string  userNum,  string  userPsw,  string  realName,  string  className,  string  phone)
    {
        
throw   new  NotImplementedException();
    }

    
#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给出不同的对话框。代码如下:

 

代码
private   void  Log_MouseLeftButtonDown( object  sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            
// 进行登陆
                DataCmdClient dcClient  =   new  DataCmdClient();
                dcClient.LoginByUserInfoCompleted 
+=   new  EventHandler < LoginByUserInfoCompletedEventArgs > (dcClient_LoginByUserInfoCompleted);
                dcClient.LoginByUserInfoAsync(UserNameBox.Text, PasswordBox.Password);
        }

        
void  dcClient_LoginByUserInfoCompleted( object  sender, LoginByUserInfoCompletedEventArgs e)
        {
            
if  (e.Result)
            {
                MessageBox.Show(
" GOOD Login " );
            }
            
else
            {
                MessageBox.Show(
" Bad Can't In " );
            }
        }

 

 

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

你可能感兴趣的:(silverlight)