更简单的解释如何在不添加服务参考的情况下进行呼叫WCF服务

时间:2009-09-02 14:34:12

标签: wcf silverlight silverlight-3.0 silverlight-2.0

Understanding WCF Services in Silverlight 2中,作者David Betz解释了如何在不在客户端应用程序中添加服务引用的情况下调用Web服务。我有几周的WCF经验,所以这篇文章是我的头脑。特别是,虽然作者给出了很多代码片段,但并没有说明会发生什么。在文章中,他为web.config文件提供了两个不同的代码片段,但没有说明发生了什么。

查看源代码,有四个项目和两个web.config文件。

到目前为止,我一直在使用Web服务的一个项目的标准Silverlight项目配置和Silverlight客户端的一个项目。

首先,文章中描述的程序是否与标准的两个项目配置一起使用?我认为会这样。

其次,有没有人知道一个更简单的例子?我对此很感兴趣,但是想要在创建新的Silverlight项目时生成默认的两个项目设置中的源代码,或者找到如何执行此操作的逐步描述(例如,添加一个类调用xxx.cs并添加此代码...,打开web.config并添加这些行...)

非常感谢 迈克托马斯

2 个答案:

答案 0 :(得分:7)

首先,一点点哲学......

如果您是未编写的WCF服务的使用者,则向客户端添加服务引用实际上是启用与该WCF服务交互的唯一机制。否则,您无法知道服务合同的外观,更不用说它的数据和消息合同了。

但是,如果您同时控制客户端和WCF服务本身,则向客户端添加服务引用是一个很好的方便,但我最近确信不会使用它。首先,在您更改合同的前几次记住更新服务参考之后,它会变得令人讨厌。在我的情况下,我有几个不同的C#项目正在使用WCF服务,所以我必须记住更新它们中的每一个。其次,创建服务引用会复制已在WCF服务中定义的合同定义。了解其含义非常重要。

假设您的WCF定义了以下类型。

[DataContract]
public class Person
{
    [DataMember] public string FirstName {get; set;}
    [DataMember] public string LastName {get; set;}
}

当您向客户端添加服务引用时,将通过元数据交换(MEX)端点检索与此类关联的元数据,并在客户端“编译”的客户端上创建此类的精确副本。因此,您的WCF服务具有Person类的定义,您的客户端也是如此,但它们是两个不同的,不同的类定义。

鉴于此,将Person类抽象为一个单独的程序集然后在WCF服务和客户端之间共享会更有意义。额外的好处是,当您更改此共享程序集中的合同定义时,您不再需要更新客户端中的服务引用,因为它已经引用了共享程序集。这有意义吗?

现在回答你的问题。就个人而言,我只在C#项目中使用WCF,而不是Silverlight。但是,我不认为情况完全不同。鉴于此,我建议您在dnrTV观看Extreme WCF视频。它提供了有关如何绕过服务引用功能的分步指南。

希望这有帮助。

答案 1 :(得分:4)

让我试试 - 我不是Silverlight开发的专家,所以如果我说一些不适用于Silverlight的东西,请耐心等待: - )

正如Matt Davis所说,“通常”的用例是:您向给定的服务URL添加服务引用。在这样做时,Visual Studio(或命令行工具svcutil.exe)将询问服务并获取其元数据 - 描述服务的信息,所有可用的调用方法,他们期望的参数等。从此,它将为您生成一个类(通常称为“客户端”或“客户端代理”),您作为客户端(=服务使用者)将用于调用该服务。您可以在“普通”Silverlight客户端项目中生成此客户端代理类,或者您可以创建自己的“服务适配器”类库,尤其是。如果您要在多个Silverlight项目中共享该客户端代理代码。事情在服务器端的结构如何在这一点完全无关紧要。

正如Matt D.所提到的,如果你这样做,你会在你的客户端获得服务,方法和数据的副本 - 那些结构与服务器相同 - 但是're 不是相同的类型 - 客户端上有一种类型,服务器有另一种类型(字段和属性虽然相同)。

这一点很重要,因为WCF的整个基本概念是消息传递 - 所有连接客户端(您)和服务器(另一端)的是消息及其结构 - 调用什么方法以及传递给该方法的值。没有其他链接 - 服务器无法“连接”到客户端代码并检查某些内容或其他内容。所有交换的都是序列化的消息(文本或二进制形式)。

如果你确实控制了两端,你可以简化一些事情 - 你可以在物理上分享服务合同(定义服务的样子以及它必须调用的方法)和数据合同(描述什么数据在服务器端和客户端都来回传递。在这种情况下,您将不会添加服务引用,您将不会复制服务和数据定义,因此事情会更容易(但只有在您控制两端时才有效)。

在这种情况下,最佳做法是将描述服务的所有内容(服务接口及其方法和数据协定)打包到服务器上的单独程序集(类库)中,然后可以将其复制到客户端,并直接从那里引用(就像你可能有的任何旧程序集)。因此,在这种情况下,您的解决方案通常至少有三个项目:

  • 您的实际Silverlight客户端项目
  • 托管Silverlight控件以进行测试的网站或网络应用
  • 服务接口程序集,其中包含服务和数据协定

所以你有它 - 我希望我涵盖了所发生事情的所有基础知识,以及为什么你想要做其中一件事。如果您需要其他信息,请随时评论此帖子并告诉我们!

马克