.NET XML web service returned collection as array - vb.net

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.

Related

My web service takes a list of Guids as an argument, but the generated reference wants an observable collection

I'm kind of confused here. I have a WCF web service
<OperationContract()>
Function StartStep(ByVal Key As Guid, WorkOrders As List(Of Guid), UserUID As Guid, Comment As String) As Boolean
But when I generate my web reference on my client, WorkOrders comes out as an observableCollection. I created a few new web services and all of the lists are doing that. A list is a fairly common data type, I assumed it would be handled properly by WCF.. could this be because I have another function that returns an ObservableCollection and that's screwing something up? Would I have to use a KnownType or something?
In the "Advanced" tab of the "Add Service Reference" dialog, you get to say how you want collections handled on the client. I guess you have it set to default to ObservableCollection, but you can select List.
Neither "List", nor "ObservableCollection", nor any other .NET type are transferred over the wire. In all cases, XML or some other such data representation is sent. The setting I mentioned earlier is about deciding how the client will interpret this XML data.

WCF Saving EF 4.1 item throws exception An item cannot be added to a fixed size Array of type

I have searched google and exhausted a fair bit of my time trying to figure out what is going on with my WCF and client Windows form app.
I am continuously getting the following error
"Unable to set field/property Ingredients on entity type Datalayer.UnitOfMeasure. See InnerException for details."
...
inner exception is
"An item cannot be added to a fixed size Array of type 'Datalayer.Ingredient[]'."
Stack Trace -
at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.<AddToCollection>b__0[T](Object collectionArg, Object item)
at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.CollectionAdd(RelatedEnd relatedEnd, Object value)
The way I have configured my solutions I have a WCF web-service which reference my DataLayer class library, I have a windows app (test app) which references the WCF services as well as DataLayer project.
If I don't reference the DataLayer in my test app, this issues does not occur however I lose the ICollection<Ingredient> to simple Ingredient[] array. Now as you can see this becomes a coding pain to initialize the array every time.
Any idea anyone? thanks in advance.
I was running into this exact error, but the accepted answer wasn't quite the solution I needed. It turns out that the client was sending a List<Order> up to my WCF service, but since the Customer.Orders property was defined as an ICollection<Order>, the WCF deserializer deserializer just deserialized it in the simplest form it could, which was an array of type Order, i.e., Order[].
The only solution I was able to come up with was to change the property in question on my POCO objects from an ICollection<Order> to a HashSet<Order>. See Stop WCF Deserializing Empty ICollection into Zero Capacity Array for a few more details.
When you are adding reference to WCF service in the test using 'Add Service Reference' there is a option to configure the default collection type for the generate proxy on the client. The default i think is array, you can change it to a generic list.
In case you are using svcutil,that too allows the same thing.
Weird. I had this same error, and was doing the right thing, calling "ToArray()". Changed it to "ToList()" and it started working fine.

How to Allow Client-Service to Build Complex Object in WCF Service?

I made a simple PasteBin demo example of what my code looks like: http://pastebin.com/GpDhPRVm
My actual Process object is extremely complex that includes adding collections of Tasks, Documents, Workflows, etc into a Process object and setting properties through methods, etc.
My PasteBin example is as simple as I can make it to show where things break down. Including the Process object in the CreateNewProcess method in my service (shown in code below), allows the service user to automatically "see" the Process object, properties and enumerators in their instance on the client side.
<ServiceContract()>
Public Interface ICreateProcess
<OperationContract()>
Sub CreateNewProcess(ByVal newprocess As Process)
End Interface
However, it does not allow them to use any of the methods like the 'AddTask' method (shown in PasteBin example) and it also doesn't expose the Task or TaskCollection objects. Even if I decorate the methods with DataContract, OperationContract, etc they still are not visible to the client service.
This is my major issue: I need the client service to be able to fully "build" the Process object and then pass it in to the CreateNewProcess method.
Another small note: (to avoid comments asking me about it) is that I made sure that all of my properties are simple types that are interoperable since this needs to be able to work for Java - not just .NET clients.
Ok, I figured it out with a little help from a buddy of mine.
Can't use methods at all outside the .svc service class; only properties, enums and sub objects will translate down to the client. (I figured this)
Then, instead of using a Collection, you have to use a generic List type.
So, instead of this:
Public Tasks As New TaskCollection() 'where TaskCollection inherits from Collection
I needed to do this:
Public Tasks As List(Of Task)
And the client will just have to build their own array of Tasks and assign it to the t.Tasks property.
This works like a charm now: http://pastebin.com/rt8HwsXY

Flex unable to find definition for type from WCF Service?

I have a WCF Service running SOAP and allowing Flex / Flash to connect to it using basicHttpBinding by using the 'Data' \ 'Import Web Service' option. Unfortunately when I consume and invoke this service within Flex it throws the following error...
Error: Cannot find definition for type
'http://schemas.datacontract.org/2004/07/System.Drawing::Size' at
mx.rpc.xml::XMLDecoder/decodeType()
...when using the following code...
// This will return an array of presentations
var service:PresentationAuthoring = new PresentationAuthoring();
var token:AsyncToken = service.getAllPresentationByClientId(
mClientId , mUserId , mWCFServiceHash );
token.addEventListener( ResultEvent.RESULT, onResult );
token.addEventListener( FaultEvent.FAULT, onFault );
This method returns an array of Presentation objects that are retreived by the service. At the moment there are no DataContracts and I'm allowing the POCO Presentation object to be serialised and punted out by the service that works fine. However, this class has a readonly property of the type System.Drawing.Size that derived from appropriate height and width properties. Looking through the generated code, it doesn't register a 'Size' class in the base import schema although it still seems to create a Size class.
An alternative has been to stop the derived property from being serialised using the [XmlIgnore] but that has not worked.
Ideally, I need a way of allowing my Flex application to communicate with my WCF service but it seems to choke on the System.Drawing.Size type and while I could change this, there are other framework types such as Point, Rectangle, etc, etc. that are utilised within the project. Has anyone else experienced this problem or can suggest an alternative approach to take?
[Please note that the WCF Service functions correctly when a .NET application consumes it.]
Kind regards and thanks in advance - S
Well the answer was to box the Size struct with a custom class that worked perfectly although it is somewhat irksome I might have to do this with (potentially) other native drawing structs. Ho hum.

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