转载出处:http://www.cnblogs.com/lxblog/archive/2012/08/02/2620393.html
今日更新本系列最后一篇,Silverlight访问控制台宿主WCF,我们分别介绍tcp信道和http信道两种方式。无论用IIS宿主还是控制台等程序宿主,对于WCF服务代码没有任何区别,但由于是Silverlight来进行调用,就会面临一个跨域的问题,我们今天也主要是来演示如何解决这个问题的,其思路就是在WCF端增加一个跨域服务,当客户端Silverlight调用的时候,Silverlight就会通过跨域服务得到跨域文件,这个方法也是之前在网上查找了大量的资料后,学习到的,在此记下并与大家分享。
首先,我们要知道跨域文件放到什么地方?前几篇IIS宿主的时候已经讲过,如果通过http绑定方式访问,跨域文件则需要放到http协议指定的端口下面(例如http://localhost:8080,则应该放到8080端口网站下),而通过net.Tcp绑定的时候,跨域文件应该放到80端口的网站下面,这是Silverlight的官方解释。好了话不多说,看代码,同样先展示一下项目结构。
项目结构
结构和以前一样,四层结构:
类库 | 说明 | 项目引用 |
LxContracts | 数据契约及操作契约 | System.Runtime.Serialization System.ServiceModel System.ServiceModel.Web |
LxSerivces | WCF服务的实现 | LxContracts [项目] System.Runtime.Serialization System.ServiceModel |
LxWcfHost | 控制台程序宿主WCF,需要修改Framework版本为.Net Framework 4.0 | LxContracts [项目] LxSerivces [项目] System.ServiceModel |
SilverlightClient | Silverlight客户端进行服务的调用 |
代码实现:
类库LxContracts(包括数据契约student.cs 操作契约IStudent.cs 和 跨域契约IDomain.cs)
using System.Runtime.Serialization; namespace LxContracts { [DataContract] public class Student { /// <summary> /// 学生编号 </summary> [DataMember] int StuId { get; set; } 学生姓名 string StuName { 所在班级 string ClassName { 联系电话 string TelPhoneNum { set; } } }
关键是这个跨域契约
类库LxServicers(集合类StudentList.cs 服务类StudentService.cs 和 契约服务DomainService.cs)
using LxContracts; namespace LxServices { class StudentList : List<Student> { public StudentList() { this.Add(new Student() { StuId = 1,StuName = 小明",ClassName = 计算机一班123456" }); 2,0)">小红计算机二班234567小兰计算机三班890123" }); } } }
关键是这个实现跨域服务
using System.IO; using System.Xml; using System.ServiceModel.Channels; class DomainService : IDomain { public System.ServiceModel.Channels.Message ProvidePolicyFile() { MemoryStream ms = new MemoryStream(); using (FileStream fs = File.OpenRead(@"clientaccesspolicy.xml")) { int length = (int)fs.Length; byte[] data = new byte[length]; fs.Position = 0; fs.Read(data,0,length); ms = new MemoryStream(data); } XmlReader reader = XmlReader.Create(ms); Message result = Message.CreateMessage(MessageVersion.None,"",reader); return result; } } }
OK,服务代码已经编写好了,我们来进行控制台宿主,我们用配置文件先演示http方式宿主
宿主控制台LxWcfHost(我们为该控制台添加一App.config 文件 和 clientaccesspolicy.xml 跨域文件,并把跨域文件的属性中的“复制到输出目录” 设置成为 “始终复制”)
此跨域文件把两种跨域文件进行了合并,可以同时支持http和Tcp
<?xml version="1.0" encoding="utf-8"?> <access-policy> cross-domain-access> policy> allow-from http-request-headers="*"> domain uri="*" /> </allow-fromgrant-tosocket-resource port="4502-4534" protocol="tcp" /> resource path="/" include-subpaths="true"> >
using System; using System.ServiceModel; namespace LxWcfHost { class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(LxServices.StudentService)); ServiceHost crossDomainserviceHost = typeof(LxServices.DomainService)); host.Opened += delegate { Console.WriteLine(服务已经启动,按任意键终止..."); }; crossDomainserviceHost.Opened += 跨域服务已经启动,按任意键终止..."); }; crossDomainserviceHost.open(); host.open(); Console.ReadKey(); host.Close(); host.Abort(); crossDomainserviceHost.Close(); crossDomainserviceHost.Abort(); } } }
xml version="1.0"configurationsystem.serviceModelbehaviorsserviceBehaviorsbehavior name="LxBehavior"> serviceMetadata httpGetEnabled="true" /> serviceDebug includeExceptionDetailInFaults="false" behaviorendpointBehaviors="DomainServiceBehavior"webHttp> servicesservice ="LxServices.StudentService" behaviorConfigurationendpoint address="" binding="basicHttpBinding" contract="LxContracts.IStudent" hostbaseAddresses> add baseAddress="http://localhost:9090/StudentSrv" service="LxServices.DomainService"="DomainServiceBehavior" binding="webHttpBinding"="LxContracts.IDomain" ="http://localhost:9090/" serviceHostingEnvironment multipleSiteBindingsEnabled/> startupsupportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0">
注意:配置文件中的跨域服务的基地址是和WCF服务的基地址端口是一样的都是9090
至此,我们的控制台宿主程序和WCF服务代码都已经完成,我们来启动一下服务:
SilverlightClient 客户端代码:
UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SilverlightClient.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Grid x:Name="LayoutRoot" Background="White"sdk:DataGrid ="dgStudnet" Grid.Row="0" AutoGenerateColumns="False"sdk:DataGrid.Columns> sdk:DataGridTextColumn Header="学生编号" Width="80" Binding="{Binding StuId}" /> ="学生姓名"="100"{Binding StuName}="所在班级"="120"{Binding ClassName}="电话号码"{Binding TelPhoneNum}/> sdk:DataGridGridUserControl>
我们为该Silverlight客户添加服务引用输入:http://localhost:9090/StudentSrv
using System.Windows.Controls; using System.Collections.ObjectModel; using SilverlightClient.WCF.StudentSrv; namespace SilverlightClient { partial class MainPage : UserControl { ObservableCollection<Student> listStudent; public MainPage() { InitializeComponent(); listStudent = new ObservableCollection<Student>(); this.Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender,System.Windows.RoutedEventArgs e) { StudentClient proxyClient = new StudentClient(); proxyClient.GetStudentCompleted += new EventHandler<GetStudentCompletedEventArgs>(proxyClient_GetStudentCompleted); proxyClient.GetStudentAsync(); } void proxyClient_GetStudentCompleted(if (e.Error == null) { listStudent = e.Result; this.dgStudnet.ItemsSource = listStudent; } } } }
OK,我们来调试一下,Silverlight客户端进行一下调用WCF服务,结果如下图:
Http绑定方式已经可以成功调用了,我们如何使用TCP方式呢,很简单,我们只要修改一下App.config文件即可完成,如下:
注意:配置文件中的跨域服务的基地址已经变成了 http://localhost:80 端口了
我们将先前的Silverlight客户端服务引用重新配置或者删除后重新添加:
然后,再次运行Silverlight客户端程序,也会得到相应的结果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。