views:

790

answers:

4

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

+2  A: 

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.

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

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.

Matt Davis
+1 for the "first a little philosophy...." :-)
marc_s
@Matt: the reason that you get an exact duplicate is that the original class is so simple. If there were code in the setters or getters, it would not be "duplicated" into the client side.
John Saunders
+1  A: 

Thanks Matt - I definitely am in control of both the Silverlight app and the Web service, so no problem there. I'll take a look at the video.

Mike Thomas

+1  A: 

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:

  • your actual Silverlight client project
  • the website or web app hosting your Silverlight control for testing
  • the service interface assembly, which contains the service and data contracts

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

marc_s
+1 for clarity.
Matt Davis
Thanks, Matt - highly appreciated!
marc_s
A: 

Thanks Matt & Marc, I took a look at Miguel Castro's video - much easier for me to understand, but I can see I have a lot to do. Thanks for the answers - both were very clear.

Mike