I have a Product Datacontract with a couple of Datamembers that are part of a WCF Service. I also serialise and store this Product Datacontract in my app using the DataContractSerializer.
Now, I want to remove some of the Datamembers of the Product Datacontract when the Service metadata (WSDL) gets generated. However, I want all Datamembers from the Product Datacontract to be available when I serialise the object within my app.
What I wanna do, actually, is this: grab hold of the WSDL generation process and remove the required Datamembers from being injected into the generated WSDL.
Thanks
Mofolo
Hacking WSDL to not contain the information will not help you. Your service will still use full serialization of your types when passing them to your client and when deserializing them from your clients. Instead of hacking WSDL and WCF use DTOs for WCF service = new set of types which will contain only properties you really want to exchange with clients. Convert your master object to DTOs and vice-versa (you can either create your own custom convertors or use some framework like AutoMapper). This is the best practice.
Related
I'm in the process of designing my first "proper" WCF service and I'm trying to get my head around how to best handle versioning of the service.
In older ASMX web services, I would create aMethodNameRequest and MethodNameResponse object for each web service method.
A request object would really just be a POCO wrapper around what would typically be in the method parameters. A response object might typically inherit from a base response object that has information about any errors.
Reading about WCF and how the IExtensibleDataObject, FaultContractAttribute and Namespacing works, it seems that I can revert back to using standard parameters (string, int etc) in my method names, and if the service is versioned, then ServiceContract inheritance can provide this versioning.
I've been looking into http://msdn.microsoft.com/en-us/library/ms731060.aspx and linked articles in that, but I was just looking for a bit of clarification.
Am I correct in thinking that dispensing with the Request/Response objects is more ideal for WCF versioning?
EDIT: I just found this article which suggests using explicit request/response object: http://www.dasblonde.net/2006/01/05/VersioningWCFServiceContracts.aspx
I don't agree that dispensing with Request/Response objects is that way to go.
There are obvious benefits of coding with messages:
you can reuse them, which avoids pass 5 ints and 3 strings to a number of different methods.
the properties are named and so can be reliably understood, whereas a parameter that is passed by value through multiple tiers could be confused, and so on.
they can be proper objects rather than just data containers, if you choose - containing private methods, etc
But you are really asking about versioning. Don't forget that you can version the messages within your service contracts. The classes in assembly can have the same name provided they are in different namespaces (e.g. v1.Request and v2.Request), and they can both implement a required interface or inherit from some base object.
They also need to be versioned for your service consumer, which can be done with xml namespaces; I've typically put the service contracts (the operations) in a namespace like http://myapp.mydomain/v1 and the messages (the request and response objects) in http://myapp.mydomain/v1/messages.
One gotcha with this approach is that if you have an operation, call it Submit, in the http://myapp.mydomain/v1 namespace then by convention / default the soap objects SubmitRequest and SubmitResponse will also exist in the same namespace (I don't remember what the run-time exception is but it confused me for a while). The resolution is to put message objects in another namespace as I've described above.
See "Versioning WCF Services: Part I" and "Versioning WCF Services: Part II".
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.
Are DataContracts in WCF nothing more than DTOs? I was reading up about WCF and just had a couple of thoughts. It would be nice if some of the DataContract objects could have methods on them so that the client could do basic things with them before or after sending or retrieving back to the service.
To me this just doesn't seem possible or logical. I could be wrong, I learn new things everyday. So would the next best thing be to treat DataContracts as DTOs and provide libraries for the clients that would create real objects from the DTOs. Objects that would contain methods.
Any guidance would be really appreciated.
Not sure if I correctly understood your answer, so correct me if I'm wrong.
You can create a class library with your DataContracts classes and share the library between the client and server. In this way class marked [DataContract] will have methods (behavior) and [DataMember] fields/properties (state).
When you will pass such objects between client and server via WCF state will be persisted, but since class library is shared you will have methods on both sides.
DTOs that are decorated as DataContract classes are real objects. They can have methods in them, but the methods are not part of the serialization process.
The main time this will cause you issues is when:
you are relying on the generated proxy version of the DataContract objects (like when you have a Silverlight client calling a WCF service, or you are calling a third party service that you have no access to the code or its libraries). The generated proxy versions will not have the methods in them, just the DataMember properties. The way to get round that is to use objects from a shared library (as already mentioned by #Insomniac).
your properties in the DataContract objects are more than just a simple get/set operation, i.e. you may have included some logic to do other operations when a property value is set. In this case even the proxy generated version will not have that logic included. The ways to get round this is to either have the shared library, or have a partial class on the client side that extends the proxy generated class.
Sharing your classes between client and server projects is the way to go. Do not forget to check in your service reference that it tries to reuse types in referenced assemblies. That way, the service reference will not generate proxy classes for the shared objects.
WCF at its core is a message-based system: your client proxy catches the call to a method, wraps up the method and all its parameters into a serialized message, and send that across the network to the service to be processed.
So yes - in the end, all that goes from client to server in WCF is a serialized message - typically in XML format. You cannot serialize behavior or methods with this approach.
I have a custom data entity (data object) that is exposed via a WCF webservice. The WCF service lives in a web application. I then have a Silverlight application with a service reference to that WCF service. When i add the service reference a proxy is generated, and that includes a version of the custom data entity.
How should i structure my code so that the data entity is declared in one place, and shared amongst the project containing the WCF service and any Silverlight applications that reference it? I want to eliminate the version of the data entity that is generated with the proxy.
There is a good example of how to do this here by Pete Brown. Using that approach you can use the same classes in both the Silverlight client and in the WCF service without having to use the generated objects.
Declare the data entities in the WCF service or a project that the service refereneces, then from the Silverlight project add the entities as links and make sure the "Reuse types in referenced assemblies" checkbox is selected from the Service Reference Settings dialog.
You can put the types in either the Silverlight or WCF side.
I have tried doing things this way and found that using DTOs instead and mapping them to the entities in the Silverlight side to be much cleaner and easier to work with although I did write a bunch of mapping code to get the DTOs into the entities and vice versa.
I´m not quite shure why anybody want to do that. You have to understand that the type you find in the proxy is a projection of the Type you have at Service server site. It´s defined in the *.g.cs files and gets generated new if you update the service reference.
In my opinion it´s the best way to have it declared in a single location, and project it. You need it in two places and it´s single defined.
I may be wrong anyway .....
From the reading I've done I'm under the impression the DataContractSerializer handles versionong issues by, if members in the request are not there it will set the default value, and if addional members are in the request but not in the definition the serializer will simply ignores these fields and not process them.
Firstly, is this assumption correct?
Secondly, could you use this DataContractSerializer instead of the XMLSerializer so you can add this versioning ability to old asmx web services? Basically, if you add new members to your web service schema request you won't need to send to every client? When you receive the request from the client you can Deserialize using the DataContractSerializer into your object.
Hope this makes sense
You can use the DataContractSerializer outside of WCF to manually deserialize and serialize object graphs. However, you cannot tell ASMX to use the serializer. You are much better of just replacing your ASMX services with WCF services.
I have used the DataContract Serializer to import xml files, it works fine.