Generic collection support in WCF - c#

Does WCF support generic collections?
I looked at the proxy object, and it seems to generate object array from a generic list collection.
Thanks

WCF does support generic collections. Over the wire it is transfered as an array of objects (this is the standard way of sending lists/arrays/etc), but WCF does the serialization/deserialization for you, so as far as your client/server are concerned, the collections are generic.
Edit: a caveat is, of course, that the collection has to be serializable. Also, take a look at this if you asking your question because your custom collection is being treated as an T[] on the client.

When you add/edit the service client, if you click on the "Advanced ..." button you will see an option allowing you to choose the collection type your service client will create. The default is System.Array, but you can change it to System.Collections.Generic.List (along with many other choices).
http://msdn.microsoft.com/en-us/library/bb514724.aspx

Using generics are fine as long as you are using WCF at both ends. If you haven't already; you must carefully consider the scenarios where a non-wcf client might need to use your services.

Related

WCF Dictionary implementing IXmlSerializable

I have some WCF services which employes default DataContractSerialization. Some of the service methods return Dictionary objects. One of the clients are generating XSD files from WCF services (biztalk related) and he is requesting to convert all dictionary types to a new dictionary type which implements IXmlSerializable.
I wonder, if there will be any unexpected results of this conversion which may affect the DataContract serialization somehow?
Update:
Server and client share the same domain dlls, clients do not generate them from service. Maybe in the question I was missing the main point; I wonder if an object is to be serizalized through datacontract serialization, implementing IXmlSerializable in the object will cause any problems.
Is your client sharing dlls with the service?
Unless he is sharing libraries (dlls) with service then making changes at the service end won't make any difference. Your WCF is returning data, not classes. That data is being reconstituted into classes which are created by the client based on the definitions in the WSDL your service returns. You can't control those generated libraries (by making chnages on the server) unless you share dlls between the client and the server.
If he wants to wrap the generated dictionaries in an IXmlSerializable dictionary then he can, or if he wants to generate a different type of dictionary then he can probably do that as well, but I don't think there is anything you can do server side.
Tell your client to use the following serializable dictionary when they need to serialize a dictionary result from a service call: C# Serializable Dictionary – a Working Example
It accepts an ordinary dictionary as constructor argument thus converts any dictionary into a serializable one. You can also return SerializableDictionary type as the service call result if you like.
There is an unexpected problem; since domain objects are already implementing data contract serialization, there is no way to implement IXmlSerializable without modifying the whole serialization mechanism.

Silverlight + WCF: configure collection type per call?

When configuring our service references in Silverlight, there is an option to choose the collection type that is generated for calls that return arrays, like so:
It is an option that you can see when you use the 'configure service reference' context menu item. I'd upload an image, but I can't do that from work...
I was wondering if there was a way to configure them on a per-call basis, so that I could have an observable collection in some cases, or an array in others? Is this type of thing possible?
It seems that out of the box, no, this type of configuration is not possible. I did stumble across a similar question while doing research on third party tools however.
How can I customize WCF client code generation?
Its answer lists a number of different option for generating client code that is custom tailored to your needs. I haven't tried any of them out though.

Adding AutoMapper Type Mapping Conventions For Generic Types in WCF Contract

I have a WCF service that uses generics in its data contract, for example (simplified):
public GetDetails(StatusField<string> status);
Now WCF supports generics by creating a non-generic equivalent type for every possible value of T in the generic. So, for the above example, the client consuming the WCF service will see the following signature for the above function:
public GetDetails(stringStatusField status);
//...
Now the client has a copy of the generic version of the StatusField class. We want to use AutoMapper in the client, to map between this generic StatusField and the types generated above by WCF (such as stringStatusField) so we can call the service. We could do this by manually creating the maps at client startup, like so:
Mapper.CreateMap<StatusField<string>, stringStatusField>();
However this is laborious as there are 50+ possible values of that WCF has converted. Extending this idea, we could use reflection to automatically create maps for all the types and this is the solution we are currently using.
Ideally what i would like to see is a solution that ties into the architecture of AutoMapper to avoid having to do the reflection manually. conceptually, this would require some way of defining a convention that AutoMapper would use to allow it to tie the two types together, similar to how it allows custom conventions to be specified when matching properties. As yet, i have not seen a way to do this and this is the question i would like answered here, if anyone knows how this can be done, specifically in relation to the above scenario.
BTW i am aware that some may be thinking of Mapper.DynamicMap() as a solution to this problem. Firstly, we dont want to use this as it means debugging could potentially be harder (as indicated by some in other posts similar to this) and also if the StatusField is deeply nested in an object graph being passed to the WCF method, im not sure this solution would work and could potentially lead to a type being incorrectly mapped and other such issues. I would really like to concretely define the allowable mappings if possible.
Unsure if AutoMapper provides the support you are after, but if it did it would be using reflection as you propose.
If you are opposed to the reflection solution due to performance concerns (which should be a one-time startup cost), then maybe a T4 template-based code generation solution might be worth considering?

Why we cant return List<T> in ASMX web services?

As developers know we cant return List<T> with web services, we can only return lists with converting them to .ToArray(); I've searched some, but cant get effective answer about Why we cant retun List with web services. Why we must convert them ToArray(); ?
Web services are supposed to be interoperable with many languages. Nearly all languages have arrays, but only .NET has the specific implementation of List<T> that you're using.
There is nothing whatsoever preventing you from returning List<T> from an ASMX web service. I have no idea why you believe that.
What may be confusing you is that XML Schema (used by the WSDL) cannot describe "lists", per se. In fact, it cannot describe arrays, either. It can describe a series of repeating elements. All collections, including arrays, are returned as sets of repeating elements.
On the client side, the client has no way to know whether the server returned List<T>, T[], or IEnumerable<T>, and no reason to care, either.
It depends on the interoperability settings of the webservice, an object like int[] is easier to understand for a non .NET language then List<int>. If you develop your web service under WCF, List<T> is supported as a return type.
What's described in the web services is a "collection". It's up to the client to determine what type of "collection" to use. If the client's .Net, when adding the service reference, click Advanced, and you'll have the ability to choose a generic list.
As far as I am aware as long as you explicitly declare you are returning a List (of T) method title you can return the object; otherwise you will receive a serialize error.
e.g
<WebMethod()> _
Public Function Search(ByVal SearchTerm As String) As List(Of 'object here')

ASP.NET Web Service Results, Proxy Classes and Type Conversion

I'm still new to the ASP.NET world, so I could be way off base here, but so far this is to the best of my (limited) knowledge!
Let's say I have a standard business object "Contact" in the Business namespace. I write a Web Service to retrieve a Contact's info from a database and return it. I then write a client application to request said details.
Now, I also then create a utility method that takes a "Contact" and does some magic with it, like Utils.BuyContactNewHat() say. Which of course takes the Contact of type Business.Contact.
I then go back to my client application and want to utilise the BuyContactNewHat method, so I add a reference to my Utils namespace and there it is. However, a problem arises with:
Contact c = MyWebService.GetContact("Rob);
Utils.BuyContactNewHat(c); // << Error Here
Since the return type of GetContact is of MyWebService.Contact and not Business.Contact as expected. I understand why this is because when accessing a web service, you are actually programming against the proxy class generated by the WSDL.
So, is there an "easier" way to deal with this type of mismatch? I was considering perhaps trying to create a generic converter class that uses reflection to ensure two objects have the same structure than simply transferring the values across from one to the other.
You are on the right track. To get the data from the proxy object back into one of your own objects, you have to do left-hand-right-hand code. i.e. copy property values. I'll bet you that there is already a generic method out there that uses reflection.
Some people will use something other than a web service (.net remoting) if they just want to get a business object across the wire. Or they'll use binary serialization. I'm guessing you are using the web service for a reason, so you'll have to do property copying.
You don't actually have to use the generated class that the WSDL gives you. If you take a look at the code that it generates, it's just making calls into some .NET framework classes to submit SOAP requests. In the past I have copied that code into a normal .cs file and edited it. Although I haven't tried this specifically, I see no reason why you couldn't drop the proxy class definition and use the original class to receive the results of the SOAP call. It must already be doing reflection under the hood, it seems a shame to do it twice.
I would recommend that you look at writing a Schema Importer Extension, which you can use to control proxy code generation. This approach can be used to (gracefully) resolve your problem without kludges (such as copying around objects from one namespace to another, or modifying the proxy generated reference.cs class only to have it replaced the next time you update the web reference).
Here's a (very) good tutorial on the subject:
http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wsproxy.mspx

Categories

Resources