I got a class called "Board" and one of its property's is an ObservableCollection. When i send the ObservableCollection through WCF (from server to client) end call it from my proxy, it's turned into an Array, which is no good for me.
Can i keep the ObservableCollection after being sent, or do i have to kick the Array till it becomes an ObservableCollection again?
Check out the 'Configure Service Reference' option in the context menu in VS for the reference. You can choose the collection type that is transmitted across the service. By default I think it is set to array but there are several choices (I believe list and observablecollection are options).
EDIT: I just checked, and unfortunately observable collection is not one of the choices. It looks like you'll have to pick from:
Array
ArrayList
LinkedList
List
Collection
BindingList
By default - no, you cannot do anything about it. WCF will serialize your structures into something that can be represented with XML schema. XML Schema has no knowledge of anything but raw, and fairly simplistic data structures. You can only transfer concrete, raw data - no "magic" behavioral addon.
There is one solution to the problem, IF you own both ends of the wire: you could put your service and data contracts into a separate class library assembly, and share those between server and client. In that case, you only ever have one single implementation of your data contract - your ObservableCollection.
If you share that assembly between your service (implementation) class, and the client (add the reference to that assembly before you "Add Service Reference" from Visual Studio!), then your client should pick up that ObservableCollection and continue to use that (instead of creating a XML schema compatible Array on the client side).
Thank you both for the answer.
I will look at both solutions when i continue the project, and will start with try and change the Collection send through the wcf service.
I'll let you know what works for me...
Related
I am working with an XML web service using VB.NET, created using VS 2010. One of my web methods returns a collection(type that inherits from list) of custom objects. It's a simple return statement, it is my understanding that .NET handles most of the tricky protocol stuff as well as serializing/unserialzing of objects.
The issue is in my consuming application when I get the the return value of the web method that returns a custom collection I get an array of the custom objects. Is this normal behavior? It will be easy enough for me to take that array and insert it into a custom collection object but if I could I would like to skip this step. Googling hasn't returned anything that I found useful. Could anyone tell me if this is typical behavior? Thanks much!
Assuming you are using WCF, try adding CollectionDataContractAttribute to your custom collection, as per Customizing Collection Types section of Collection Types in Data Contracts.
In the case you are using your service by setting up a Service Reference in the consuming application, then an even easier method would be to right-click the service name, select Configure Service Reference..., and about 1/3rd the way down of the dialog that pops up there will be a dropdown with "Collection type:" label. Default is to use System.Array, but here you can easily change it to use whichever collection type you prefer.
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.
We are using a WCF Data Service to broker our data server side, and give third parties easy OData access to our data. The server side of things has been relatively easy. The client side, on the other hand, is giving us fits.
We are converting from regular Entity Framework to Data Services, and we've created an assembly which contains the generated client objects that talk to the data service (via a Service Reference). Those classes are partial, so we've added some logic and extended properties to them. This all works great.
The issue we are having is that we need to process our objects at save time, because they need to do some advanced serialization before they are sent over the wire. The DataServiceContext class contains two events: WritingEntity and ReadingEntity. The ReadingEntity event actually happens at the correct time for us (post object deserialization). The WritingEntity event happens at the WRONG time for us (post object serialization).
Is there any way to catch an object before it's written to the request, so that we can call a method on entity that is about to be written?
Obviously we could just loop through the Entities list, looking for any entity that is not in a state of Unchanged or Deleted, and call the appropriate method there...but this would require me to add special code every time I wanted to call SaveChanges on the context. This may be what we need to do, but it would be nice if there was a way to catch the entities before they are written to XML for sending to the service.
Currently there's no hook in the DataServiceContext to do what you want. The closest I can think of is the approach you suggested with walking all the entities and findings those which were modified. You could do this in your own SaveChanges-like method on the context class (which is also partial).
If I have an object that holds the parameters for my method. I need to change the Object to have an additional property. I have full control over the server, but not over all of the clients. Will this change make those clients break?
I am using a self-hosted service with a binary endpoint.
I am new to WCF so my apologies if this is a silly question.
I guess you are asking about a class that represents your DataContract.
Learn about DataContract versioning and how various changes in your DataContract affect the compatibility in MSDN
In short the answer is No, it will not break the client code. The serialized graph of the data contract will deserialize to the available data members matching by their names and assigned through the property setter method. Obviously in this case, your newly added data member will not have value. Since you have full control on the server side code, you just have to make sure this newly added member need to be dealt in such a way that it is meaningful in the new implementation and allow for default/unassigned value.