一步一步学Silverlight 2系列(14):数据与通信之WCF

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章将从Silverlight 2基础知识、数据与通信、自定义控件、动画、图形图像等几个方面带您快速进入Silverlight 2开发。

本文将简单介绍在Silverlight 2中如何与WCF进行通信。

简单示例

在本示例中,我们将通过WCF来获取一个最新随笔的列表,在Silverlight中显示出来,最终完后效果如下所示。

TerryLee_Silverlight2_0065

先定义一个数据契约:

[DataContract]
public class Post
{
    public Post(int id,string title,string author)
    {
        this.Id = id;
        this.Title = title;
        this.Author = author;
    }

    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Title { get; set; }

    [DataMember]
    public string Author { get; set; }
}

在Web项目中添加一个WCF Service文件,命名为Blog.svc

TerryLee_Silverlight2_0063

定义服务契约:

[ServiceContract]
public interface IBlog
{
    [OperationContract]
    Post[] GetPosts();
}

实现服务,这里可以是从数据库或者其他数据源读取,为了演示方便,我们直接初始化一个集合:

public class Blog : IBlog
{
    public Post[] GetPosts()
    {
        List<Post> posts = new List<Post>()
        {
            new Post(1,"一步一步学Silverlight 2系列(13):数据与通信之WebRequest","TerryLee"),
            new Post(2,"一步一步学Silverlight 2系列(12):数据与通信之WebClient","TerryLee"),
            new Post(3,"一步一步学Silverlight 2系列(11):数据绑定","TerryLee"),
            new Post(4,"一步一步学Silverlight 2系列(10):使用用户控件","TerryLee"),
            new Post(5,"一步一步学Silverlight 2系列(9):使用控件模板","TerryLee"),
            new Post(6,"一步一步学Silverlight 2系列(8):使用样式封装控件观感","TerryLee")
        };

        return posts.ToArray();
    }
}

修改Web.config中的服务配置,这里使用basicHttpBinding绑定,并且开启httpGetEnabled,以便后面我们可以在浏览器中查看服务:

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="TerryLee.SilverlightDemo27Web.BlogBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service behaviorConfiguration="TerryLee.SilverlightDemo27Web.BlogBehavior"
            name="TerryLee.SilverlightDemo27Web.Blog">
            <endpoint address="" binding="basicHttpBinding" contract="TerryLee.SilverlightDemo27Web.IBlog">
            </endpoint>
        </service>
    </services>
</system.serviceModel>

设置一下Web应用程序的端口号为固定端口52424,在浏览器中输入http://localhost:52424/Blog.svc,看看服务是否正常:

TerryLee_Silverlight2_0064

好了,现在服务端我们就实现完成了。现在编写界面展示部分,XAML如下:

<Grid Background="#46461F">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Border Grid.Row="0" Grid.Column="0" CornerRadius="15"
            Width="240" Height="36" Background="Orange"
            Margin="20 0 0 0" HorizontalAlignment="Left">
        <TextBlock Text="最新随笔" Foreground="White"
                   HorizontalAlignment="Left" VerticalAlignment="Center"
                   Margin="20 0 0 0"></TextBlock>
    </Border>
    <ListBox x:Name="Posts" Grid.Row="1" Margin="40 10 10 10">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Id}" Height="40" Foreground="Red"></TextBlock>
                    <TextBlock Text="{Binding Title}" Height="40"></TextBlock>
                    <TextBlock Text="{Binding Author}" Height="40" Foreground="Orange"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

在Silverlight项目中添加服务引用,输入地址http://localhost:52424/Blog.svc,输入命名空间BlogService。

TerryLee_Silverlight2_0066

添加完成后,我们可以在对象浏览器中浏览一下生成的客户端对象:

TerryLee_Silverlight2_0067

当然大家也可以手工去编写客户端的代码,请参考WCF的相关内容,这里不再赘述。下面编写调用服务并获取数据,这里仍然是采用异步模式,由于在WCF服务的配置中我们采取了BasicHttpBinding,客户端也要采用BasicHttpBinding。我们需要注册GetPostsCompleted事件处理方法,以便完成后回调,同时调用GetPostsAsync()方法获取数据。完整的代码如下所示:

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
    }

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        Binding binding = new BasicHttpBinding();
        EndpointAddress endPoint = new EndpointAddress(
                "http://localhost:52424/Blog.svc");

        BlogClient client = new BlogClient(binding, endPoint);
        client.GetPostsCompleted += new EventHandler<GetPostsCompletedEventArgs>(client_GetPostsCompleted);
        client.GetPostsAsync();
    }

    void client_GetPostsCompleted(object sender, GetPostsCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            Posts.ItemsSource = e.Result;
        }
    }
}

至此,一个完整的在Silverlight 2中调用WCF的示例就完成了,运行后效果如下:

TerryLee_Silverlight2_0065 

结束语

本文简单演示了在Silverlight 2中如何与WCF进行通信,你可以从这里下载示例代码。

下一篇:一步一步学Silverlight 2系列(15):数据与通信之ASMX

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Tag标签: Silverlight,XAML
posted @ 2008-03-09 21:41 TerryLee 阅读(14506) 评论(73)  编辑 收藏 网摘 所属分类: [03]  银光点亮世界

  回复  引用  查看    
#1楼2008-03-09 21:43 | 侯垒      
博主的写作速度真是太快了.佩服佩服.
  回复  引用  查看    
#2楼[楼主]2008-03-09 21:45 | TerryLee      
@侯垒
呵呵,周末有空就多写点,顺便也学习一下:)

  回复  引用  查看    
#3楼2008-03-09 21:47 | Justin      
速度是够快的,佩服!
可否分享一下是用了什么学习方法,学习了哪些资源,或者是那本书?这么快!

  回复  引用  查看    
#4楼[楼主]2008-03-09 21:49 | TerryLee      
@Justin
Silverlight 2刚出来,似乎还没有相关的书吧:)

参考SDK和http://silverlight.net/Learn/

  回复  引用  查看    
#5楼2008-03-09 22:20 | 梦里花落知多少      
我的机器跑VS2008实在是费劲啊,又改回2005了:(

  回复  引用  查看    
#6楼2008-03-09 22:22 | Cat Chen      
不错的系列,期待~
  回复  引用  查看    
#7楼[楼主]2008-03-09 22:22 | TerryLee      
@梦里花落知多少
不装2008,暂时就体验不到Silverlight 2了哦:)

  回复  引用  查看    
#8楼[楼主]2008-03-09 22:23 | TerryLee      
@Cat Chen
多谢支持:)

  回复  引用  查看    
#9楼2008-03-10 08:59 | 木野狐(Neil Chen)      
还不懂 wcf。学习一下。
  回复  引用    
#10楼2008-03-10 10:45 | hlink[未注册用户]
楼主真是.net和silverlight的骨灰级狂热者啊!周六日都不休息发布这么多牛X的文章,服了!
  回复  引用    
#11楼2008-03-10 10:49 | 戏梦_wxf[未注册用户]
我想向博主请教一下,在silverlight1.0和1.1中,我可以通过initparam,和contex向silverlight传递字符串与对象。在silverlight2.0中如何实现呢?
  回复  引用    
#12楼2008-03-10 13:59 | slici[未注册用户]
感同身受
  回复  引用  查看    
#13楼[楼主]2008-03-10 14:27 | TerryLee      
@木野狐(Neil Chen)
呵呵,张逸翻译的那本书不错,可以看一下:)

  回复  引用  查看    
#14楼[楼主]2008-03-10 14:28 | TerryLee      
@hlink
呵呵,谢谢,Silverlight 2确实功能很强,就多看了一些:)

  回复  引用  查看    
#15楼[楼主]2008-03-10 14:30 | TerryLee      
@戏梦_wxf
这块我还不了解,我这几天看一下再回答:)

  回复  引用  查看    
#16楼[楼主]2008-03-10 14:30 | TerryLee      
@slici
:)

  回复  引用    
#17楼2008-03-14 10:36 | huson[未注册用户]
为什么我一改变WCF Service的名字,service就不好用了?Web.Config里面相应的service name也修改了啊!

谢谢

  回复  引用  查看    
#18楼[楼主]2008-03-14 22:55 | TerryLee      
@huson
估计是哪儿没有修改完,应该是没有问题的,Web.config、还有.svc文件等都检查一遍吧:)

  回复  引用    
#19楼2008-03-19 10:03 | hhhh[未注册用户]
添加服务引用前都是对的,添加后就会报错。

  回复  引用  查看    
#20楼[楼主]2008-03-19 10:09 | TerryLee      
@hhhh
你下载文章中提供的示例代码,运行试一下。

  回复  引用    
#21楼2008-03-19 10:14 | hhhh[未注册用户]
就是配置好webconfig以后,然后测试了wcf也是正确的,然后在sl项目中导入服务就会报错
  回复  引用    
#22楼2008-03-19 10:19 | hhhh[未注册用户]
还想请教个问题,就是我看你教程中设置了fontfamily是微软雅黑,我设置了以后出来的字体怎么还是不变的?
  回复  引用  查看    
#23楼[楼主]2008-03-19 11:05 | TerryLee      
@hhhh
那这个问题我就不清楚了,我这儿没有出现过类似的问题

可能是机器上没有装微软雅黑字体

  回复  引用    
#24楼2008-03-21 12:13 | ondogdog[未注册用户]
运行出错“System.ServiceModel.ProtocolException”,在Referenec.cs的返回值的时候,怎样解决呢?
  回复  引用  查看    
#25楼[楼主]2008-03-21 22:14 | TerryLee      
@ondogdog
我也不太清楚这个错误

  回复  引用  查看    
#26楼2008-04-28 11:35 | 镜涛      
学习!
  回复  引用  查看    
#27楼2008-05-06 23:34 | 傻样精英      
你好,看到了你的文章我也做了一个wcf和silverligth的练习,但是用silverlight调用的时候,报错如下:
operation is not valid due to the current state of the object

怀疑是endpoint没找到,请问下什么原因啊?程序我用邮件发给你了,不知道收到没有

  回复  引用    
#28楼2008-07-08 22:58 | botsing[未注册用户]
我的是silverlight beta2的,为什么会出现
The remote server returned an unexpected response: (404) Not Found.这样的错误.
这个问题有没有解决方法呢?

  回复  引用  查看    
#29楼[楼主]2008-07-09 09:49 | TerryLee      
@botsing
很可能是跨域的问题造成的。

  回复  引用    
#30楼2008-07-09 22:28 | botsing[未注册用户]
@TerryLee
嗯,应该是这个问题,那有没有解决方法啊,网上找的基本上都是把wcf发不到iis上之后的办法,在vs2008中调试时有没有解决方法,还是只能发布到iis中才能用?

  回复  引用    
#31楼2008-07-12 22:32 | ooxxxxxxxxx[未注册用户]
@TerryLee

你好,我下载您的包运行,结果完全OK。

不过,当然在这个解决方案内新建一个网站(端口8888)。然后将Sliverlight附加到此网站中,通过此站访问端口:52424这个站上的svc。

这时候列表中无法显示内容。但是我在52424网站根目录,分别添加了clientaccesspolicy.xml和crossdomain.xml测试。结果还是出不来。

我要怎么做呢?

谢谢。

  回复  引用    
#32楼2008-07-13 23:48 | botsing[未注册用户]
终于发现错在哪了,忘了改成basicHttpBinding绑定了,郁闷
  回复  引用  查看    
#33楼[楼主]2008-07-13 23:52 | TerryLee      
@botsing
Silverlight中只支持basicHttpBinding绑定

  回复  引用    
#34楼2008-07-15 21:54 | botsing[未注册用户]
@TerryLee
嗯,现在知道了,谢谢楼主

  回复  引用  查看    
#35楼2008-07-16 08:04 | 杰仔      
void client_GetPostsCompleted(object sender, GetPostsCompletedEventArgs e)


GetPostsCompletedEventArgs怎么我这里提示缺少引用,下载你的源码也一样的

  回复  引用  查看    
#36楼[楼主]2008-07-21 10:26 | TerryLee      
@杰仔
重新添加一下引用再看看,另外,该示例在Beta 1下的,注意版本问题。

  回复  引用    
#37楼2008-07-22 20:43 | MeteorCui[未注册用户]
搞不懂, Silverlight2 里怎么没有System.Data.Linq的命名空间
  回复  引用  查看    
#38楼[楼主]2008-07-22 23:46 | TerryLee      
@MeteorCui
为什么Silverlight 2中要有System.Data.Linq命名空间呢?我说过很多次了,Silverlight是一种客户端技术,它不可以直接访问数据库,所以System.Data.Linq就没有必要了。

  回复  引用    
#39楼2008-08-05 09:45 | 吕不韦[未注册用户]
不能访问库,应该可以访问xml了吧,用xml也可以实现动态更新啊
  回复  引用  查看    
#40楼[楼主]2008-08-06 13:25 | TerryLee      
@吕不韦
请问这个XML文件在哪儿?客户端 还是 服务端?

  回复  引用  查看    
#41楼2008-09-28 11:49 | SnailFly      
The remote server returned an unexpected response: (404) Not Found.我也出现了这样的错误,但我的是basicHttpBinding绑定,这个问题有没有什么好的解决方法啊?

  回复  引用    
#42楼2008-10-28 16:01 | lau[未注册用户]
silverlight里不支持DataSet..有没有好的方法.如得到数据库返回的表.
  回复  引用  查看    
#43楼[楼主]2008-10-28 21:18 | TerryLee      
@lau
既然是数据库的数据表,就一定能够通过对象来表示,何不返回一个List<T>呢?

  回复  引用    
#44楼2008-11-04 19:15 | az[未注册用户]
路过
  回复  引用  查看    
#45楼[楼主]2008-11-05 09:17 | TerryLee      
@az
:)

  回复  引用  查看    
#46楼2008-11-23 23:54 | BAsil      
和botsing一样,我也忘了改basicHttpBinding,看来比较容易出错,默认是wsHttpBinding
  回复  引用  查看    
#47楼[楼主]2008-11-24 09:57 | TerryLee      
@BAsil
:)

  回复  引用    
#48楼2009-02-25 12:39 | CloudFly
楼主你好,我在定义服务契约中多添加了个方法,当然,在Blog.svc.cs中也对此TestMethod001()方法进行了定义。
[ServiceContract]
public interface IBlog
{
[OperationContract]
Post[] GetPosts();
Post[] TestMethod001();
}

为什么在浏览器中输入http://localhost:52424/Blog.svc验证的时候看不到TestMethod001()这个方法呢?

  回复  引用    
#49楼2009-02-25 12:40 | CloudFly
楼主你好,我在定义服务契约中多添加了个方法,当然,在Blog.svc.cs中也对此TestMethod001()方法进行了定义。
[ServiceContract]
public interface IBlog
{
[OperationContract]
Post[] GetPosts();
Post[] TestMethod001();
}
为什么在浏览器中输入http://localhost:52424/Blog.svc验证的时候看不到TestMethod001()这个方法呢?

  回复  引用    
#50楼2009-02-25 12:41 | CloudFly
楼主你好,我在定义服务契约中多添加了个方法,当然,在Blog.svc.cs中也对此TestMethod001()方法进行了定义。
[OperationContract]
Post[] GetPosts();
Post[] TestMethod001();
为什么在浏览器中输入http://localhost:52424/Blog.svc验证的时候看不到TestMethod001()这个方法呢?

  回复  引用    
#51楼2009-02-25 13:06 | CloudFly
楼主你好,我在定义服务契约中多添加了个方法,当然,在Blog.svc.cs中也对此TestMethod001()方法进行了定义。
[ServiceContract]
public interface IBlog
{
[OperationContract]
Post[] GetPosts();
Post[] TestMethod001();
}

为什么在浏览器中输入http://localhost:52424/Blog.svc验证的时候看不到TestMethod001()这个方法呢?

  回复  引用    
#52楼2009-02-25 17:24 | 寒星_offline[未注册用户]
to CloudFly:
[ServiceContract]
public interface IBlog
{
[OperationContract]
Post[] GetPosts();
Post[] TestMethod001();
}
只是说明了GetPosts()是OperationContract,而TestMethod001()不是。

正确的写法是:
[ServiceContract]
public interface IBlog
{
[OperationContract]
Post[] GetPosts();
[OperationContract]
Post[] TestMethod001();
}

  回复  引用    
#53楼2009-02-26 17:13 | test00001[未注册用户]
BlogClient client = new BlogClient(binding, endPoint);


BlogClient是从哪儿来的啊?在你的源码中没看到定义

  回复  引用    
#54楼2009-03-06 10:06 | 初学silverlight
LZ我先谢谢你的文章,不过我是刚刚接触到这个技术的,看不太明白,能不能把关键的步骤写进来,比如在哪个目录创建哪个文件,是什么文件,比如这篇的开头就是“先定义数据契约”,可是有几个初学者知道这是什么意思呢?希望LZ考虑我们初学者,谢谢。
  回复  引用    
#55楼2009-03-11 13:34 | 问题总是很多[未注册用户]
楼主你好,按照楼主介绍的过程开发完毕过后,如何将这样的程序部署到IIS上面呢?需要进行什么设置呢?特别是WCF跨域访问的问题,很让人头疼!除了需要在IIS的根目录下添加两个跨域访问的XML文件意外,还需要对程序做那些改动才可以正常运行呢?恳请指点啊!
  回复  引用    
#56楼2009-03-19 11:47 | grt[未注册用户]
wcf的服务有二个,一个是wcf服务,另外还有一个是带silverligh功能的wcf,二者有何不同?怎样选用?
请楼主帮助回答。

  回复  引用    
#57楼2009-04-15 03:36 | Yigi[未注册用户]
lz你好!我按照你的教程,自己做了一个项目,但是步骤没错,就是在端口号设置那,我每次设置完后,添加服务引用后,它都会自动生成另外一个端口号,保存了也没有。后来我把服务器地址都改成自动生成的端口号,运行出来后,绑定数据无法显示出来。
但是,直接下载你的代码运行之后,一切都很正常。
不明白这是怎么回事?

  回复  引用    
#58楼2009-04-16 01:37 | Yigi[未注册用户]
知道原因了,忘了在页面中定义“UserControl_loaded”..- -b
  回复  引用    
#59楼2009-05-04 17:47 | 匿名[未注册用户]
貌似很钟爱list泛型啊
  回复  引用    
#60楼2009-05-06 14:39 | afaand20
错误提示:
尝试请求 URI“http://localhost:52424/Blog.svc”时发生错误。这可能是因为在没有适当的跨域策略的情况下试图以跨域方式访问服务,或者是策略不适用于 SOAP 服务。您可能需要与服务所有者联系以发布跨域策略文件,确保策略允许发送与 SOAP 相关的 HTTP 头。请参阅内部异常以了解详细信息。
请问怎么消除跨域访问呢?

  回复  引用    
#61楼2009-05-12 18:08 | JackyHo[未注册用户]
Terry大哥,asmx 測試沒問題,可以顯示數據,但加到silverlight內沒有數據顯示,也沒有錯誤,大應是哪裡出錯? 謝謝.
  回复  引用    
#62楼2009-05-19 14:30 | lyp[未注册用户]
就因为basicHttpBinding,让我费了那么多时间... 郁闷
  回复  引用    
#63楼2009-05-19 14:31 | lyp[未注册用户]
不过总算成功了。谢谢楼主!
  回复  引用  查看    
#64楼[楼主]2009-05-19 16:41 | TerryLee      
@JackyHo
在Complete事件中跟踪一下,看看返回的错误信息是什么?

  回复  引用  查看    
#65楼[楼主]2009-05-19 16:41 | TerryLee      
@lyp
客气了,呵呵




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1097821




历史上的今天:
2006-03-09 重载还是覆写?

相关文章:

相关链接: