更简单地解释如何在不添加服务引用的情况下调用WCF服务
在了解 Silverlight 2 中的 WCF 服务中,作者 David Betz 解释了如何在客户端应用程序中不添加服务引用的情况下调用 Web 服务。我有几周的 WCF 经验,所以这篇文章让我无法理解。特别的是,作者虽然给出了很多代码片段,但是并没有说明什么地方。在文章中,他为 web.config 文件提供了两个不同的代码片段,但没有阐明发生了什么。
查看源代码有四个项目和两个 web.config 文件。
到目前为止,我一直在使用标准的 Silverlight 项目配置,其中一个项目用于 Web 服务,另一个项目用于 Silverlight 客户端。
首先,本文中描述的过程是否适用于标准的两个项目配置?我想会的。
其次,有人知道一个更简单的例子吗?我对此非常感兴趣,但希望查看在创建新 Silverlight 项目时生成的默认两个项目设置中的源代码,或者找到如何执行此操作的逐步说明(例如,添加一个类)称为 xxx.cs 并添加此代码...,打开 web.config 并添加这些行...)
非常感谢 迈克·托马斯
In Understanding WCF Services in Silverlight 2, the author, David Betz, explains how to call a web service without adding a service reference in the client application. I have a couple of weeks experience with WCF, so the article was over my head. In particular, although the author gave a lot of code snippets, but does not say what goes where. In the article, he provides two different code snippets for the web.config file, but does not clarify what's going on.
Looking at the source code there are four projects and two web.config files.
So far, I have been using the standard Silverlight project configuration of one project for the web service and one for the Silverlight client.
Firstly, does the procedure described in the article work with the standard two project configuration? I would think it would.
Secondly, does anyone know of a simpler example? I am very interested in this, but would like to either see source code in the default two project setup which is generated when a new Silverlight project is made, or find a step by step description of how to do this (eg, add a class called xxx.cs and add this code..., open web.config and add these lines...)
Many thanks
Mike Thomas
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,一点哲学...
如果您是一个不是您编写的 WCF 服务的使用者,那么向您的客户端添加服务引用实际上是您必须启用与该 WCF 服务交互的唯一机制。否则,您无法知道服务契约是什么样的,更不用说它的数据和消息契约了。
但是,如果您同时控制客户端和 WCF 服务本身,则向客户端添加服务引用会非常方便,但我最近确信不要使用它。首先,在您最初几次更改合同后,记住更新您的服务参考号会变得很麻烦。就我而言,我有几个不同的 C# 项目正在使用 WCF 服务,因此我必须记住更新每个项目。其次,创建服务引用会复制 WCF 服务中已定义的协定定义。了解这一点的含义很重要。
假设您的 WCF 定义了以下类型。
当您向客户端添加服务引用时,将通过元数据交换 (MEX) 端点检索与此类关联的元数据,并在客户端“编译”时在客户端创建此类的精确副本。因此,您的 WCF 服务有 Person 类的定义,您的客户端也有,但它们是两个不同的、不同的类定义。
鉴于此,将 Person 类抽象为一个单独的程序集,然后在 WCF 服务和客户端之间共享该程序集更有意义。额外的好处是,当您更改此共享程序集中的协定定义时,您不再需要更新客户端中的服务引用,因为它已经引用了共享程序集。这有道理吗?
现在回答你的问题。就我个人而言,我只在 C# 项目中使用过 WCF,而不是 Silverlight。然而,我认为情况并没有根本不同。鉴于此,我建议您观看 dnrTV 上的Extreme WCF 视频。它提供了如何绕过服务参考功能的分步指南。
希望这有帮助。
First, a little philosophy...
If you are a consumer of a WCF service that you did not write, adding a service reference to your client is really the only mechanism you have to enable interaction with that WCF service. Otherwise, you have no way of knowing what the service contract looks like, much less its data and message contracts.
However, if you are in control of both the client and the WCF service itself, adding a service reference to the client is a nice convenience, but I've recently been convinced not to use it. For one, it becomes a nuisance after the first few times you change your contract to remember to update your service reference. And in my case, I have several different C# projects that are consuming the WCF service, so I have to remember to update each one of them. Second, creating a service reference duplicates the contract definitions that are already defined in your WCF service. It is important to understand the implications of this.
Let's say your WCF defines the following type.
When you add a service reference to your client, the metadata associated with this class is retrieved through the metadata exchange (MEX) endpoint, and an exact replica of this class is created on the client side that your client "compiles" against. So your WCF service has a definition of the Person class, and so does your client, but they are two different, distinct class definitions.
Given this, it would make more sense to abstract the Person class into a separate assembly that is then shared between the WCF service and the client. The added benefit is that when you change the contract definitions within this shared assembly, you no longer have to update the service reference within the client because it is already referencing the shared assembly. Does that make sense?
Now to your question. Personally, I've only used WCF within C# projects, not Silverlight. However, I do not think things are radically different. Given that, I would suggest that you watch the Extreme WCF video at dnrTV. It gives a step-by-step guide for how to bypass the service reference feature.
Hope this helps.
让我尝试一下 - 我不是 Silverlight 开发方面的专家,所以如果我说的话不适用于 Silverlight :-)
正如 Matt Davis 提到的,“通常”用例是这样的:您添加一项服务对给定服务 URL 的引用。在此过程中,Visual Studio(或命令行工具 svcutil.exe)将询问服务并获取其元数据 - 描述服务的信息、所有可调用的方法、它们期望的参数等。由此,它将为您生成一个类(通常称为“客户端”或“客户端代理”),您作为客户端(=服务使用者)将使用该类来调用服务。您可以在“普通”Silverlight 客户端项目中生成此客户端代理类,或者您也可以创建自己的“服务适配器”类库,尤其是。如果您要在多个 Silverlight 项目之间共享该客户端代理代码。在这一点上,服务器端的结构如何完全无关。
正如 Matt D. 还提到的,如果您这样做,您将在客户端中获得服务、其方法和数据的副本 - 这些副本在结构上与服务器具有的相同 - 但它们< em>不同相同的类型 - 您在客户端有一种类型,服务器有另一种类型(尽管字段和属性是相同的)。
记住这一点很重要,因为 WCF 的整个基本思想是消息传递 - 所有连接客户端(您)和服务器(另一端)的都是消息及其结构 - 使用什么方法调用以及传递给该方法的值。没有其他链接 - 服务器无法“连接”到客户端代码并检查某些内容或其他内容。所有交换的都是序列化消息(文本或二进制形式)。
如果您确实控制了两端,则可以稍微简化一些事情 - 您可以在物理上共享服务契约(服务的定义以及它必须调用的方法)和数据契约(对正在使用的数据的描述)在服务器端和客户端上来回传递)。在这种情况下,您不会添加服务引用,也不会重复服务和数据定义,因此事情会更容易一些(但只有在您控制两端时才有效)。
在这种情况下,最佳实践是将所有描述服务的内容(服务接口及其方法和数据契约)打包到服务器上的单独程序集(类库)中,然后您可以将其复制到客户端,并直接从那里引用(就像您可能拥有的任何旧程序集一样)。因此,在这种情况下,您的解决方案中通常至少有三个项目:
现在您已经有了它- 我希望我涵盖了正在发生的事情的所有基础知识,以及为什么你想做一件事或另一件事。如果您需要更多信息,请随时对此帖子发表评论并告诉我们!
马克
Let me try - I'm not an expert at Silverlight development, so bear with me if I say something that doesn't apply to Silverlight :-)
As Matt Davis mentioned, the "usual" use case is this: you add a service reference to a given service URL. In doing so, Visual Studio (or the command-line tool svcutil.exe) will interrogate the service and grab its metadata - information that describes the service, all the available methods to call, what parameter they expect etc. From this, it will generate a class for you (usually called the "client" or "client proxy"), which you as a client (=service consumer) will use to call the service. You can have this client proxy class generated inside your "normal" Silverlight client project, or you could possibly create your own "service adapter" class library, esp. if you will be sharing that client proxy code amongst several Silverlight projects. How things are structured on the server side of things is totally irrelevant at this point.
As Matt D. also mentioned, if you do it this way, you're getting copies of the service, its methods, and its data, in your client - those are identical in structure to what the server has - but they're not the same type - you on the client side have one type, the server has another (the fields and properties are identical though).
This is important to remember since the whole basic idea of WCF is message-passing - all that connects the client (you) and the server (the other end) are the messages and their structure - what method to call and what values to pass into that method. There's no other link - there's no way a server can "connect" to the client code and check something or whatever. All that gets exchanged is serialized messages (in text or binary form).
If you do control both ends, you can simplify things a bit - you can physically share the service contract (the definition what the service looks like and what methods it has to call into) and the data contract (the description of what data is being passed back and forth) on both the server side as well as the client side. In this case, you won't be adding a service reference, you won't be duplicating the service and data definitions, so things are a bit easier (but it only works if you're in control of both ends).
In this case, best practice would be to package up all that describes the service (the service interface with its methods and the data contracts) into a separate assembly (class library) on the server, which you can then copy to the client side, and reference directly from there (like any old assembly you might have). So in this case, you would typically have at least three projects in your solution:
So there you have it - I hope I covered all the basics of what's going on, and why you would want to do one or the other thing. If you need additional info, don't hesitate to comment on this posting and let us know!
Marc