Silverlight与WCF通信(二) :Silverlight通过netTcpBinding访问IIS宿主WCF

   本篇我们介绍Silverlight通过net.Tcp方式访问IIS宿主的WCF。

   Windows (Process) Activation Service (简称:WAS  全称:Windows 进程激活服务)是 IIS7.0 特有的新增功能,比IIS6 的功能更加强大,它提供并支持除HTTP之外的更多协议。由于Net.tcp 协议在 Silverlight 中的不支持传输层安全性,我们尽量在安全性比较好的Intranet 环境中使用此传输方式。

   本例子的开发环境是:Win7旗舰版+VS2010+Silverlight4+IIS7。项目代码和结构和上一篇一样,WCF服务代码没有任何改变,只不过是WcfHost.web 中的Web.Config 中配置代码进行了改变,为了方便查看,我再贴一下项目结构和代码:

项目结构(如图):

代码实现:

类库LxContracts:(包括数据契约Student.cs和操作契约IStudent.cs)

Student.cs 代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace LxContracts
{
    [DataContract]
    public class Student
    {
        /// <summary>
        /// 学生编号
        /// </summary>
        [DataMember]
        public int StuId { get; set; }

        /// <summary>
        /// 学生姓名
        /// </summary>
        [DataMember]
        public string StuName { get; set; }

        /// <summary>
        /// 所在班级
        /// </summary>
        [DataMember]
        public string ClassName { get; set; }

        /// <summary>
        /// 联系电话
        /// </summary>
        [DataMember]
        public string TelPhoneNum { get; set; }
    }
}
IStudent.cs 代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace LxContracts
{
    [ServiceContract]
    public interface IStudent
    {
        [OperationContract]
        List<Student> GetStudent();
    }
}

类库LxServices:( 改类库包括一个模仿获取数据库集合类StudentList.cs和服务类StudentService.cs)

StudentList.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LxContracts
{
    public class StudentList:List<Student>
    {

        public StudentList()
        {
            this.Add(new Student() { StuId = 1, StuName = "小明", ClassName = "计算机一班", TelPhoneNum = "123456" });
            this.Add(new Student() { StuId = 2, StuName = "小红", ClassName = "计算机二班", TelPhoneNum = "234567" });
            this.Add(new Student() { StuId = 2, StuName = "小兰", ClassName = "计算机三班", TelPhoneNum = "890123" });
        }
    }
}
StudentService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LxContracts;

namespace LxServices
{
    public class StudentService:IStudent
    {
        public List<Student> GetStudent()
        {
            //实际情况应该为从数据库读取
            //本例手动生成一个StudentList
            StudentList ListStuent = new StudentList();
            return ListStuent;
        }
    }
}

站点WcfHost.web

站点WcfHost.web,这是一个Asp.net 空web应用程序。

1、右击” WcfHost.web”—“添加”—“新建项”—“wcf服务”,命名为”StudentSrv.svc” 。如图:

在项目中删除”StudentSrv.svc.cs”文件和”IStudentSrv.cs”文件。右击”StudentSrv.svc”文件,选择”查看标记”,将代码修改为:

<%@ ServiceHost Language="C#" Service="LxServices.StudentService" %>

 2、修改webconfig 文件,代码如下:(配置文件和第一篇http方式 发生了改变)

WebConfig
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="LxBehavior">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <!--这个必须写,Silverlight不支持具有安全性的 NetTcpBinding,写了之后,客户端引用就变成了CustomBinding-->
    <bindings>
      <netTcpBinding>
        <binding name="myTcpBinding">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    <services>
      <service name="LxServices.StudentService" behaviorConfiguration="LxBehavior">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration="myTcpBinding" contract="LxContracts.IStudent" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    
    <!--关闭 ASP.NET 兼容性模式-->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  
  <!--设置默认页面为StudentSrv.svc-->
  <system.webServer>
    <defaultDocument>
      <files>
        <remove value="default.aspx" />
        <remove value="iisstart.htm" />
        <remove value="index.html" />
        <remove value="index.htm" />
        <remove value="Default.asp" />
        <remove value="Default.htm" />
        <add value="StudentSrv.svc" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>

   注意:(1) 配置文件中把 <serviceMetadata httpGetEnabled="false" /> 设置成了false;<service>节点中也去掉了 basicHttpBinding方式的Endpoint,目的是我们的服务元节点地址和传输方式只提供net.Tcp方式的。当然也可以不用去掉,这样服务就提供两种通道了。(2)netTcp方式 必须增加元数据发布节点mex,因此wcf的服务元数据地址就是:net.tcp://localhost:端口号/StudentSrv.svc/mex

部署服务:

1、添加必要的组件:

    1)打开 “控制面板”—“程序和功能”—“打开或关闭Windows功能”。节点“Microsoft .Net Framework 3.5.1 ”下面的两项WCF Http 激活和WCF No Http 激活都必须安装。如下图:

        

    2)安装IIS6兼容性和管理工具:

        

    3)查看服务:确保服务Net.Tcp Listener Adapter、Windows Process Activation Service和World Wide Web Publishing Service 都已经启动。

2、在IIS7中进行部署:

   1)打开IIS7,右击”应用程序池—“添加应用程序池。名称输入为:”WcfTcpPool”,Framework版本选择为:4.0,如下图:

       

   2)右击网站—“添加网站”;网站名称为:WcfTcpWeb;应用程序池选择我们刚刚创建的”WcfTcpPool”;物理路径选择我们项目下的WcfHost.web的所在路径;http端口我选择的是7070,如下图:

       

   3)选择我们刚刚创建的网站,在IIS最右面的操作列表中,选择”高级设置”;在”已启用的协议” 中输入 net.tcp ,每个协议之间用 逗号 分隔,如下图:

       

   4)为网站添加绑定:右击WcfTcpWeb网站—“编辑绑定”,添加绑定,选择”net.tcp” ,绑定信息输入“4505:*”,如下图:

       

     注意:Silverlight 只能访问介于45024534范围之间的端口。

   5)右击我们的网站,选择”管理网站”—“浏览”;浏览器会显示如下信息:(我们的服务配置已经成功)

      

在Silverlight中进行调用:

1、为Silverlight程序添加WCF:

  “右击”—“SiverlightDemo”—“添加服务引用”—“输入服务地址”net.tcp://localhost:4505/StudentSrv.svc/mex --点击“前往”,就会找到服务,命名为”WCF.StudentSrv”后,点击”确定”。  

   

2、在Silverlight中调用WCF:(以下代码跟第一篇实例一样,为了查看方便我又贴了一下)

MainPage.xaml中添加”DataGrid”控件。

MainPage.xaml 代码
<sdk:DataGrid x:Name="dgStudnet" Grid.Row="0" AutoGenerateColumns="False">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header="学生编号" Width="80" Binding="{Binding StuId}" />
                <sdk:DataGridTextColumn Header="学生姓名" Width="100" Binding="{Binding StuName}" />
                <sdk:DataGridTextColumn Header="所在班级" Width="120" Binding="{Binding ClassName}" />
                <sdk:DataGridTextColumn Header="电话号码" Width="100" Binding="{Binding TelPhoneNum}" />
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
MainPage.cs 代码
namespace SilverlightDemo
{
    public partial class MainPage : UserControl
    {
        ObservableCollection<Student> listStudent;
        public MainPage()
        {
            InitializeComponent();
            listStudent = new ObservableCollection<Student>();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            StudentClient proxyClient = new StudentClient();
            proxyClient.GetStudentAsync();
            proxyClient.GetStudentCompleted += new EventHandler<GetStudentCompletedEventArgs>(proxyClient_GetStudentCompleted);
        }

        void proxyClient_GetStudentCompleted(object sender, GetStudentCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                listStudent = e.Result;
                this.dgStudnet.ItemsSource = listStudent;
            }
        }
    }
}

 3、运行:右击 "SilverlightDemo" ,选择“调试”--“启动新实例”,会产生以下异常信息:

 这还是跨域问题,怎么解决呢?当然还是需要跨域文件(clientaccesspolicy.xml)了,但这个跨域文件和上一篇http绑定方式的跨域文件内容有所不同,放置的位置也有所不同。

clientaccesspolicy.xml 代码
<?xml version="1.0" encoding="utf-8"?> 
<access-policy> 
   <cross-domain-access> 
      <policy> 
         <allow-from http-request-headers="*"> 
            <domain uri="*" /> 
         </allow-from> 
         <grant-to> 
            <socket-resource port="4502-4534" protocol="tcp" /> 
            <resource path="/" include-subpaths="true"/> 
         </grant-to> 
      </policy> 
   </cross-domain-access> 
</access-policy>

 但是这个跨域文件放到哪里呢?

 netTcp方式的跨域文件并不是放到我们项目中宿主wcf的网站WcfHost.web的根目录,而是放到IIS 80端口网站的根目录。我计算机IIS下80端口的网站是Default Web Site,因此放到此网站根目录下面:

 再次运行我们的Silverlight 程序,会发现WCF调用成功,第一次运行有点慢,耐心等待一下,结果如下图:

至此,本篇主要介绍了Silverlight和WCF基于net.tcp 方式传输的配置及说明,下一篇我们利用Silverlight和WCF实现一个全双工通信的例子。

 

posted @ 2012-05-04 22:35  Rising_Sun  阅读(4139)  评论(9编辑  收藏  举报