Will changing an Object signature break a WCF method call using that Object? - wcf

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.

Related

Add data persistence to WCF Service

I'm in charge of a WCF service. Our client has requested an override feature: If a call is resubmitted, allow the operation to proceed despite warnings. I need a way to persist data from recent calls so I can detect a resubmission. I thought making the service durable, part of WF3, would resolve the problem; however, my service uses .NET 4.5 which marks WF3 as obsolete. I've been trying to find the WF4 equivalent, but nothing's clicked for me. All the examples presume a workflow which I lack.
What is the best solution for my needs?
Edit:
According to this question, a static variable should meet my needs, but I haven't been able to get one to persist between calls.
A static variable did meet my needs.
I used a property to interact with my static variable, and in the getter I would remove some of the old data. For some reason, having that call in the getter prevented the static variable from persisting. I relocated the clean up code (incidentally I didn't need the property anymore), and the static variable persisted.

Unable to access the service instance from within an implementation of IDataContractSurrogate

this is my first post, and I really have tried hard to find an answer, but am drawing a blank thus far.
My implementation of IDataContractSurrogate creates surrogates for certain 'cached' objects which I maintain (this works fine). What doesn't work is that in order for this system to operate effectively, it needs to access the service instance for some properties of the instance which it is maintaining from the interaction with its client. Also, when my implementation of IDataContractSurrogate works in its 'client mode' it needs access to the properties of the client instance in a similar way. Access to the information from the client and service instance affects how I create my surrogate types (or rather SHOULD do if I can answer this question!)
My service instancing is PerSession and concurrent.
On the server side, calls to GetDataContractType and GetDeserializedObject contain a valid OperationContext.Current from which I can of course retreive the service instance. However on the client side, none of the calls yield an OperationContext.Current. We are still in an operation as I am translating the surrogate types to the data contract types after they have been sent from the server as part of its response to the client request so I would have expected one? Maybe the entire idea of using OperationContext.Current from outside of an Operation invocation is wrong?
So, moving on, and trying to fix this problem I have examined the clientRuntime/dispatchRuntime object which is available when applying my customer behaviour, however that doesn't appear to give me any form of access to the client instance, unless I have a message reference perhaps... and then calling InstanceProvider. However I don't have the message.
Another idea I had was to use IInstanceProvider myself and then maybe build up a dictionary of all the ones which are dished out... but that's no good because I don't appear to have access to any session related piece of information from within my implementation of IDataContractSurrogate to use as a dictionary key.
I had originally implemented my own serializer but thats not what I want. I'm happy with the built in serializer, and changing the objects to special surrogates is exactly what I need to do, with the added bonus that every child property comes in for inspection.
I have also looked at applying a service behavior, but that also does not appear to yield a service instance, and also does not let me set a Surrogate implementation property.
I simply do not know how to gain access to the current session/instance from within my implementation IDataContractSurrogate. Any help would be greatly appreciated.
Many thanks,
Sean
I have solved my problem. The short answer is that I implemented IClientMessageFormatter and IDispatchMessageFormatter to accomplish what I needed. Inside SerializeReply I could always access the ServiceInstance as OperationContext.Current is valid. It was more work as I had to implement my own serialization and deserialization, but works flawlessly. The only issue remaining would be that there is no way to get the client proxy which is processing the response, but so far that is not a show stopper for me.

WCF Serialization Information outside class definition

Suppose this simple scenario:
My client has an already working .net application and he/she wants to expose some functionality through WCF. So he gives me an assembly, containg a public class that exposes the followig method.
OrderDetail GetOrderDetail (int orderId) // Suppose OrderDetail has {ProductId, Quantity, Amount)
Now, I want some members of OrderDetail (Amount) not to be serialized.
According to http://msdn.microsoft.com/en-us/library/aa738737.aspx, the way to do this is by means of the [DataContract] and [DataMember]/[IgnoreDataMember] attributes. However, that's not an option for me because I can not modify client's source code. So I'm looking for a way to specify which members I want to serialize out, outside the type's definition. Something that should look like this:
[OperationContract]
[IgnoreMember(typeof(OrderDetail), "Amount" )]
OrderDetail QueryOrder(int orderId){
return OrderDetail.GetOrderDetail(orderId)
}
Is there any way to to this?
Thanks,
Bernabé
Don't send the clients objects across the wire, create a DTO from the clients object containing only the information that you want to send and send that instead.
This allows you to control exactly what information gets sent, and is in keeping with the WCF intentions of passing messages and not objects
So create an OrderDetailDto class and populate this with the data from the OrderDetail returned by the call to the method in the clients code. Decorate The OrderDetailDto with the DataContract and DataMember attributes (you can rename the class in here so that when it is returned by WCF it is returned with the name OrderDetail)
Repeat this for all objects in the client code, so that at the service boundary you basically convert from DTO->Client objects and Client Objects->DTO
EDIT
Whilst there might be an option which allows what you have asked for (I am not aware of one, but hopefully someone else might be) consider that when you send use your client objects as DTOs you are using them for two purposes (the client object and the message contract), which is against the Single Responsibility Principle and when you get them on the client side they will not be the same client side objects, just DTOs with the same properties, you will not be able to get behaviour in the client side objects (at least not without sharing libraries on the server side and client side).
By binding the data contract to the objects you also end up having to manage the changes to client objects and data contracts as one thing. When they are separate you can manage the changes to client side objects without neccessarily changing the DTOs, you can just populate the differently.
Whilst it seems like it is a lot of work to create the DTOs, in the end I think it will be worth it.
You will have to write a wrapper class that only exposes the desired properties and simply calls the class your client provided to gets its values.
The only other option would be to emit a new dynamic class using reflection and serialize that (see http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.aspx), but its probably not worth the effort unless you need to build a lot of wrapper classes.

ObservableCollection turns into an Array after transported using WCF

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...

WCF and Object

I am trying to pass an object into a WCF web service, the object I am passing in is a Server object, I then want to be able to call TestConnection();
The issue I am having is that Server is the base class and there are several derived classes of Server, i.e. SqlServer2005Server, OracleServer and ODBCServer that I want to use
I want to be able to pass in a Server Object and then determine its type, cast it and then use the method
public string TestServerConnection(Server server)
{
if (server.ConnectionType == "SqlServer")
{
SqlServer2005Server x = (SqlServer2005Server)server;
// Tests connection to server and returns result
return x.TestConnection();
}
return "";
}
'Server' the base class implements IServer
I am unable to cast it, can you advise?
Much Appreciated
Phill
As Daniel Pratt said, in the end, you are only shuttling XML (not always the case, but most of the time you are) across the wire.
If you used a proxy generator to generate the definition of the Server type, then you aren't going to be able to make calls on the methods of Server, because only properties (semantically at least) are used in the proxy definition. Also, you can't cast to the derived types because your instance is really a separate type definition, not the actual base.
If the Server type is indeed the same type (and by same, I mean a reference to the same assembly, not just in name and schema only), then you can do what Steve said and use the KnownType attribute on the Server definition, adding one attribute for each derived class.
However, like he said, that convolutes your code, so be careful when doing this.
I thought that using inversion of control would work here, but you run into the same situation with generic references to specific providers.
You need to add the KnownType declaration to your service contract for each derived class. There are ways to automate this (since it obviously convolutes code and breaks inheritance), but they require a lot of work.
Does the object you're passing represent a "live" connection to a DBMS? If the answer is yes, there is no hope of this ever working. Keep in mind that despite the pretty wrapper, the only thing your web service is getting from the caller is a chunk of xml.