How do I reuse complex types accross different services? - wcf

I have 2 separate java services that use a complex type that is a exactly the same but takes an email object as a parameter like:
class Email{
Description{get;}
Address{get;}
}
The services look something like this:
emailBasketBallTeam(email);
emailTennisTeam(email);
Is there a way that I can specify a contract for the email object or somehow reuse the email object in different services despite them being in completely different namespaces?

Unlike wsdl /sharetypes, you need to consume one service at a time, but you can re-use types from existing assemblies.
With svcutil, you can use the /reference switch. I believe you can also do this in the IDE in the designer.

Related

Service Contract Namespace : Why

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.

WCF Contract restrict string values

We are defining some WCF contracts for a project.
In one case we want so send over a status field. We though of just sending this over as a text.
Can we specify in the WCF contract that only these x string valuses are allowed?
Would it be better to use enums?
We will be interoperating with java web services.
No you can't, but you could use enums which are then turned into the schema equivalent of a restricted list of strings. This is also helpful to non-WCF clients because they can easily see what the range of allowed string values are.
Unfortunately enums come with some unfortunate baggage in WCF when it comes to versioning. Specifically, you can't just add a new enum and not break existing WCF clients. So adding a new enum is considered a breaking change.
You will need to weigh these two options and decide which is best for you. If you choose "pure" string, then you will need to validate the values yourself. This can be done generically by writing an IParameterInspector which you can hook to all your services that might use the data contract that you're interested in constraining.

Can WCF service transmit type (client doesn't know this type) information?

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.

Problem with WCF and multiple namespaces - sharing object types across multiple service references

i have two web services. One with user functionality, one with admin functionality.
Both services effectively work with the same object types, for instance:
AdminService provides functionality for deleting/modifying Customer objects
UserService provides functionality for listing/reading Customer objects
Now in the client i have two service references, Webservices.Admin and Webservices.User.
If i use the UserService to retrieve Customer objects, i cannot manipulate those via the AdminService, since the UserService retrieves objects of type Webservices.User.Customer, however the AdminService works with objects of type Webservices.Admin.Customer.
On the server side both types are identical, just belong to different namespaces in the client.
Now the question: How can i share types across different service references?
Check out https://github.com/geersch/WcfSvcMap
By tweaking the Reference.svcmap file you can make sure only one class is generated for each DataContract used by the different service references.
Note: Remember to delete the content of the node before pressing 'Update Service Reference'
If you're controlling both ends of the communication, and both ends are .NET only, you could do this:
put all your contracts, including your data contracts, into a separate "Contracts" assembly
reference that assembly in both the server side implementation code, as well as the client side code
If you do this, when adding the service references, WCF will find and use that shared assembly, and not create new types for the entitites. In your case, you'd only ever have one type Contracts.Customer or whatever you're dealing with.
This works only if you control both ends of the wire and have .NET on both ends! But in that case, it's a great way to share contracts - especially data contracts - across both the server and any number of clients.
Use the slsvcutil to create the WCF proxy on the clientside (assuming the clientside is a .net application), reference the DLL which contains your objects and it will be used for all endpoints that pass the same object in the DLL
Open Visual Studio Command prompt from the Start -> Visual Studio 2008 -> Tools -> Visual Command Prompt
goto directory similar to
C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Tools
type slsvcutil and follow the syntax
slsvcutil http://somewcfservice:8080 /r:CommonLibrary.dll
where CommonLibrary.dll is the dll that contains the business objects
[edit] fixed the fact that the project is a silverlight project
There is an easy way to share types between client and service, just by adding reference to shared type assembly to your client BEFORE adding the service reference.
You can find the detailed scenario and sample project there:
http://blog.walteralmeida.com/2010/08/wcf-tips-and-tricks-share-types-between-server-and-client.html

Can Server-side and Client-side WCF Share Validation Library?

Greetings!
I am using a WCF library on an application server, which is referenced by an IIS server (which is therefore the client). I would like to put my validation in a place so that I can just call .Validate() which returns a string array of errors (field too short, missing, etc). The problem is, such functions don't cross the WCF boundary and I really don't want to code the same logic in the WCF service and in IIS/WCF client. Is there a way to use extension methods or something similar so both side can use use a .Validat() method which calls the same code?
Many thanks for any ideas!
Steve
If you control both sides of the wire, i.e. the server-side (service) and the client-side, then you could do the following:
put all your service and data contracts into a shared assembly
reference that "Contracts" assembly from both the server and the client
manually create the client proxy (by deriving from ClientBase<T> or by creating it from a ChannelFactory<T>) - do not use "Add Service Reference" or svcutil.exe!
put all validation logic into a shared assembly
reference that shared validation assembly from both projects
If you want to use a shared validation assembly, you must make sure the data types used on your server and client are identical - this can only be accomplished if you also share service and data contracts. Unfortunately, that requires manual creation of the client proxy (which is really not a big deal!).
If you'd use "Add Service Reference", then Visual Studio will inspect the service based on its metadata, and create a new set of client-side objects, which look the same in terms of their fields and all, but they're a separate, distinct type, and thus you wouldn't be able to use your shared validation on both the server-side and the client-side objects.
Do you have a problem with sending the data over to the server to be validated? In other words, your service interface actually offers the "Validate" method and takes a data contract full of data, validates it and returns a List where T is some kind of custom ValidationResult data contract that contains all the info you need about validation warnings/errors.
In a service architecture, you can't trust the client, who could theoretically be some other company altogether, to have done proper data validation for you. You always need to do it at the service layer and design for communication of those validation issues back to your client. So if you're doing that work at the server anyway, why not open that logic up to the clients so they can use it directly? Certainly the clients can (should) still do some kind of basic input validation such as checking for null values, empty strings, values out of range, etc, but core business logic checks should be shipped off to the service.