Serialization issues calling WCF service from iPhone MonoTouch app
I have a WCF service on a Windows Server and I am trying to invoke the service from an iPhone Application in MonoDevelopment. The web service client was generated using Silverlight service generation utility and copied to the iPhone development project in the MonoTouch environment.
So the service is pretty straightforward. I have a method that calls a GetCustomers()
methods and returns a List<Customer>
. I can create the client successfully in the MonoTouch iPhone application code. The method does execute and if I try to do a count on the result it tells me there are 91 records (Northwind database / Customers table). So I am sure that the service is working just fine.
Problem is when I try to access any property of Customer object I get the following error:
The CustomerName property does have public getter and setter
but the following exception says it does not. I need some help if someone can walk me through what I am doing wrong!
Exception in async operation: System.Runtime.Serialization.InvalidDataContractException: DataMember property 'System.String CustomerName' on type 'NorthwindService.Customer' must have both getter and setter. at System.Runtime.Serialization.SharedContractMap.GetMembers (System.Type type, System.Xml.XmlQualifiedName qname, Boolean declared_only) [0x00116] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs:553 at System.Runtime.Serialization.SharedContractMap.Initialize () [0x00053] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs:516 at System.Runtime.Serialization.KnownTypeCollection.RegisterContract (System.Type type) [0x0004f] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs:766 at System.Runtime.Serialization.KnownTypeCollection.TryRegister (System.Type type) [0x0002a] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serializati开发者_如何学JAVAon/System.Runtime.Serialization/KnownTypeCollection.cs:593 at System.Runtime.Serialization.KnownTypeCollection.RegisterCollection (System.Type type) [0x0000f] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs:666 at System.Runtime.Serialization.KnownTypeCollection.TryRegister (System.Type type) [0x00062] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs:605 at System.Runtime.Serialization.KnownTypeCollection.InsertItem (Int32 index, System.Type type) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs:389 at System.Collections.ObjectModel.Collection`1[T].Add (.T item) [0x0000c] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Collections.ObjectModel/Collection.cs:72 at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlDictionaryReader reader, Boolean verifyObjectName) [0x0000c] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/DataContractSerializer.cs:267 at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.Xml.XmlDictionaryReader reader) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/XmlObjectSerializer.cs:74 at System.ServiceModel.Dispatcher.DataContractMessagesFormatter.MessageToParts (System.ServiceModel.Description.MessageDescription md, System.ServiceModel.Channels.Message message) [0x000b8] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs:364 at System.ServiceModel.Dispatcher.BaseMessagesFormatter.DeserializeReply (System.ServiceModel.Channels.Message message, System.Object[] parameters) [0x00043] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs:175 at System.ServiceModel.ClientRuntimeChannel.Request (System.ServiceModel.Description.OperationDescription od, System.Object[] parameters) [0x0016a] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:500 at System.ServiceModel.ClientRuntimeChannel.DoProcess (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00038] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:443 at System.ServiceModel.ClientRuntimeChannel.Process (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:425
No, the service is not working just fine. It appears it's an async method, so when your first call appears to be successful, it may not be really unless you close the async call and get the return value. The processing and counting of the result may very well have been successful, but the actual serialization of the result -- which requires the Customer type to have both a setter and getter -- is not.
This is one of the few exceptions in WCF that is almost always right and very specific. Are you sure the Customer type has both a getter and setter? Are their access levels consistent?
The MonoTouch linker will exclude any code that isn't used from the final native iOS binaries. In your case, the getter/setter probably isn't used in your project and so isn't getting into the native version.
To fix this, you can decorate your DataMember properties with the MonoTouch.Foundation.Preserve attribute. Or, stick the Preserve attribute on the class that is your DataContract and pass in AllMembers = true, like the example below.
[DataContract,
MonoTouch.Foundation.Preserve(AllMembers=true)]
public class EntityClass
{
[DataMember]
public string Field {get;set;}
}
精彩评论