I'm pretty new to WCF and SOA, so I apologize if the question is poor.
The way I see it, if I could specify a contract's Name and Namespace in app.config, I could change the service that my client contracts use at runtime rather than compile time. Without the ability to specify Name and Namespace in app.config, my client contracts are limited to connecting to services with contracts with the same name and in the same namespace. Is this right?
So is there a way to choose Name and Namespace for a given contract in app.config? If not, why not?
What you ask for doesn't make sense. The name and namespace identify the contract. The contract cannot change without changing the client. This is why service versioning is often performed by adding a new contract (with a new name/namespace combination), not by changing an existing contract.
You should think of a contract as being an unbreakable agreement between the client and service - you will always provide that set of operations.
You can, on the other hand, change the endpoint that your client references if you decide you'd like your client to use a different implementation of the contract. You can also change the binding by which the implementation is reached. But you must always maintain the same contract, unless you'd like to begin lying to your clients.
Related
Bit confused with specifying a namespace for the service contract. Can understand with respect to a normal class,
My understanding about namespace
In normal OOPs model, say Employee class is part of Microsoft name space as well as Google name space. But since we may add reference to Google as well as Microsoft assembly in our project; hence to differentiate Employee's we have namespace, since when we say
Employee emp = new Employee()... compiler really doesn't really know which employee we are referring to?
Similarly, with respect to web service how does it matter? May I request an explicit example to explain the case please? For example
[ServiceContract(Namespace="Company.Matching.Algo")]
It's used - just like regular .NET namespaces - to keep things apart.
Having a namespace helps when you have multiple services that might end up all having similar methods exposed. With a namespace, they can all have a method called GetVersion or something, and the WSDL document will be able to keep them apart based on their namespace.
Also, namespaces are often used for versioning, so your first WCF service might have a service namespace of http://yourcompany.com/MyService/2011/08 and have five methods. If you later on introduce a v2 of your service, which might have 10 methods, and you put it into a separate namespace of http://yourcompany.com/MyService/2011/12 then you can keep those things separate - and an "old" client can still call the "old" service with (/2011/08) and use its method, while new clients can already call the new service with more capabilities.
From RebuildAll:
A note on namespaces: namespaces ARE NOT URLS!. They might look like one, like in my examples, but there is no such subdomain as schemas actually in existence. Namespaces follow the URI format, but are not actual addresses. They can be used to identify schemas, because usually a company owns a domain name. Thus using that as the schema namespace creates something unique. And that is exactly what namespaces should be: unique.
The namespace is important for serializing and deserializing objects.
In your example you can have the same Employee class on the server and client, and send an Employee object from one to the other over a web service. If the namespace is different it will be null when you deserialize on the otherside.
I'm working on a simple plug-in framework. WCF client need to create an instance of 'ISubject' and then send back to service side. The 'ISubject' can be extended by the user. The only thing client knows at runtime is ID of a subclass of 'ISubject'.
Firstly, client need to get type information of a specific subclass of 'ISubject'. Secondly, client using reflection to enumerate all members to create a custom property editor so that each member can be asigned with proper value. Lastly, client create an instance of that subclass and send back to service.
The problem is how does client get the type information through WCF communication?
I don't want client to load that assembly where the subclass (of 'ISubject') exists.
Thanks
First, you need to be aware that there is no magic way that WCF will provide any type information to your client in the scenario you have descibed. If you are going to do it, you will have to provide a mechanism yourself.
Next, understand that WCF does not really pass objects from server to client or vice versa. All it passes are XML infosets. Often, the XML infoset passed includes a serialized representation of some object which existed on the sender's side; in this case, if the client knows about that type (i.e. can load the type's metadata from its assembly), it can deserialize the XML to instantiate an identical object on the client side. If the client doesn't have the type metadata, it can't: this is the normal case with WCF unless data contract types are in assemblies shared by both server and client implementations (generally not a good idea).
The way WCF is normally used (for example if the client is implemented using a "Service Reference" in Visual Studio), what happens is that the service publishes WSDL metadata describing its operations and the XML schemas for the operation parameters and return values, and from these a set of types is generated for use in the client implementation. These are NOT the same .NET types as the data contract types used by the service implementation, but they are "equivalent" in the sense that they can be serialized to the same XML data passed over the network. Normally this type generation is done at design time in Visual Studio.
In order to do what you are trying to do, which is essentially to do this type generation at runtime, you will need some mechanism by which the client can get sufficient knowledge of the structure of the XML representing the various types of object implementing ISubject so that it can understand the XML received from the service and generate the appropriate XML the service is expecting back (either working with the XML directly, or deserializing/serializing it in some fashion). If you really, really want to do this, possible ways might be:
some out-of-band mechanism whereby the client is preconfigured with the relevant type information corresponding to each subclass of ISubject that it might see. The link provided in blindmeis's answer is one way to do that.
provide a separate service operation by which the client can translate the ID of the subclass to type metadata for the subclass (perhaps as an XSD schema from which the client could generate a suitable serializable .NET type to round trip the XML).
it would also be feasible in principle for the service to pass type metadata in some format within the headers of the response containing the serialized object. The client would need to read, interpret and act on the type infomation in an appropriate fashion.
Whichever way, it would be a lot of effort and is not the standard way of using WCF. You will have to decide if it's worth it.
I think you might be missing something :)
A major concept with web services and WCF is that we can pass our objects across the network, and the client can work with the same objects as the server. Additionally, when a client adds a service reference in Visual Studio, the server will send the client all the details it needs to know about any types which will be passed across the network.
There should be no need for reflection.
There's a lot to cover, but I suggest you start with this tutorial which covers WCF DataContracts - http://www.codeproject.com/KB/WCF/WCFHostingAndConsuming.aspx
To deserialize an object the receiving side will need to have the assembly the type is defined in.
Perhaps you should consider some type of remoting or proxying setup where the instance of ISubject lives on one side and the other side calls back to it. This may be problematic if you need to marshal large amounts of data across the wire.
wcf needs to know the real object(not an interface!) which should be sent across the wire. so you have to satisfy the server AND the clientproxy side from the WCF service that they know the types. if you dont know the object type while creating the WCF service, you have to find a way to do it in a dynamic way. i use the solution from here to get the knownTypes to my WCF service.
[ServiceContract(SessionMode = SessionMode.Required]
[ServiceKnownType("GetServiceKnownTypes", typeof(KnownTypeHelper))]//<--!!!
public interface IWCFService
{
[OperationContract(IsOneWay = false)]
object DoSomething(object obj);
}
if you have something "universal" like the code above, you have to be sure that whatever your object at runtime will be, your WCF service have to know this object.
you wrote your client create a subclass and sent it back to the service. if you want to do that, WCF(clientproxy and server!) needs to know the real type of your subclass.
I have a WCF service that supports about 10 contracts, we have been supporting a client with all the business rules specific to this client now we have another client who will be using the exact same contracts (so we cannot change that) they will be calling the service exactly the same way the previous client called now the only way we can differentiate between the two clients is by one of the input parameters. Based on this input parameter we have to use a slightly different business logic – the logic for both the Client will be same 50% of the time the remainder will have different logic (across Business / DAL layers) . I don’t want to use if else statement in each of contract implementation to differentiate and reroute the logic also what if another client comes in. Is there a clean way of handling a situation like this. I am using framework 3.5. Like I said I cannot change any of the contracts (service / data contract ) or the current service calling infrastructure for the new client. Thanks
Can you possibly host the services twice and have the clients connect to the right one? Apart from that, you have to use some kind of if-else, I guess.
I can't say whether this is applicable to you, but we have solved a similar problem along this path:
We add a Header information to the message that states in which context some logic is called.
This information ends up in a RequestContext class.
We delegate responsibility of instantiating the implementation of the contract to a DI Container (in our case StructureMap)
We have defined a strategy how certain components are to be provided by the container:
There is a default for a component of some kind.
Attributes can be placed on specializations that denote for which type of request context this specialization should be used.
This is registered into the container through available mechanisms
We make a call to the Container by stating ObjectFactory.With(requestcontext).getInstance<CONTRACT>()
Dependencies of the service implementations are now resolved in a way that the described process is applied. That is, specializations are provided based ultimately on a request information placed in the header.
This is an example how this may be solvable.
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
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.
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
i have recently been involved in developing a WCF service which acts as a kind of multicast relay (i.e. accepts some incoming data, does some processing and then sends it off to multiple other external services). this service (which i will refer to as "my service") is fed data by a second internal service.
this data is going to be relayed from my service as XML held in a string. therefore my service could simply accept a string as an parameter to a method request - but this is not ideal as we lose type safety.
the second service has a class that encapsulates all of the information which my service requires to be processed, and eventually relayed to the external services.
the second service exposes this class in it's data contract. Ideally, in order to maintain type safety, and without requiring lots of changes to the second service's implementation, i should accept this type of class as an argument to my service operation.
what would be the best way for me to say in my datacontract that i require this type of class without duplicating code? could i add a service reference to this second class, and then use the proxy class which is created in my data contract?
i just can't get my head around this, even though it seems like a trivial problem!
cheers for any help!
If you are trying to avoid duplication of classes, put your class declaration in its own assembly and share that dll between all parties in the WCF Service. When you create your service reference you can choose which assemblies are shared (assuming you use the VS GUI service utility).
The use of a proxy class might be a good avenue as well. If you expose your main data class as a data contract, then create a proxy of that, the proxy will have a version of the exposed class that can be used by your other services.