WCF array serialization error

I have a fairly simple WCF service, running as a Windows service with WSHttpBinding and consumed by a website. The service works most of the time. Sometimes I cause the following error when calling various methods in a service:

Array length '0' provided by the get-only collection of type 'System.String[]' is less than the number of array elements found in the input stream. Consider increasing the length of the array.

I went through the debugger, and the results of the function returns look correct. I am new to WCF and have no idea what might make this error know where to start looking for problems.

Any help is greatly appreciated and I can provide additional information if necessary.

Update 2 . I solved this problem and answer below.

Update

Service agreement

 [ServiceContract(Namespace="http://Foo.Service")] public interface IExchangeManager { [OperationContract] IList<DistributionGroup> GetDistributionGroups(Organisation org); } 

Implementation

 public class ExchangeManager : IExchangeManager { public IList<DistributionGroup> GetDistributionGroups(Organisation org) { var groups = new List<DistributionGroup>(); // Stuff to get groups return groups; } } 

A distribution group object has several row properties and a List<User> . I commented on the setting of these properties and the error persists, so I do not believe that the problem is with these objects.

Service binding configuration

 protected override void OnStart(string[] args) { if (serviceHost != null) { serviceHost.Close(); } var baseAddress = "http://hosted.local:8001/ExchangeManager/service"; serviceHost = new ServiceHost(typeof(ExchangeManager), new Uri(baseAddress)); // Check to see if the service host already has a ServiceMetadataBehavior ServiceMetadataBehavior smb = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>(); // If not, add one if (smb == null) { smb = new ServiceMetadataBehavior(); } smb.HttpGetEnabled = true; smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; serviceHost.Description.Behaviors.Add(smb); // Check to see if we already have a debug behaviour ServiceDebugBehavior debug = serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>(); // if not found - add behavior with setting turned on if (debug == null) { serviceHost.Description.Behaviors.Add(new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true }); } else { debug.IncludeExceptionDetailInFaults = true; } // Add end points // Setting quotes to try and fix array length problem var binding = new WSHttpBinding(); binding.MaxReceivedMessageSize = 1073741824; var myReaderQuotas = new XmlDictionaryReaderQuotas(); myReaderQuotas.MaxStringContentLength = 1073741824; myReaderQuotas.MaxArrayLength = 1073741824; myReaderQuotas.MaxBytesPerRead = 4096; myReaderQuotas.MaxDepth = 32; myReaderQuotas.MaxNameTableCharCount = 16384; binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null); serviceHost.AddServiceEndpoint(typeof(IExchangeManager), binding, ""); serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); serviceHost.Open(); } 

Full exception

 System.ServiceModel.Dispatcher.NetDispatcherFaultException: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://Foo.Service:GetDistributionGroupsResult. The InnerException message was 'Array length '0' provided by the get-only collection of type 'System.String[]' is less than the number of array elements found in the input stream. Consider increasing the length of the array.'. Please see InnerException for more details. ---> System.Runtime.Serialization.SerializationException: Array length '0' provided by the get-only collection of type 'System.String[]' is less than the number of array elements found in the input stream. Consider increasing the length of the array. at System.Runtime.Serialization.XmlObjectSerializerReadContext.ThrowArrayExceededSizeException(Int32 arraySize, Type type) at ReadArrayOfstringFromXmlIsGetOnly(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns) at ReadUserFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] ) at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns) at ReadArrayOfUserFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns) at ReadDistributionGroupFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] ) at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns) at ReadArrayOfDistributionGroupFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract) at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns) at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest) --- End of inner exception stack trace --- Server stack trace: at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest) at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest) at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters) at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Services.Exchange.IExchangeManager.GetDistributionGroups(Organisation org) 

I get this error for a number of methods of my service, and all of these methods have worked and still work in some cases. The error occurs in service methods that have a void return type, so I don't think it complains about the data returned by the service.

+4
source share
1 answer

The problem was with the User object. I noticed that for the void method, which was an error, the exact error message says that it cannot deserialize the user parameter, not the return result. From this, I came to the conclusion that there must be something in the User that caused the problem.

Finding an example that worked and one that was broken, I compared them. I noticed that the only differences between the two users were 2 arrays. One is called a group and one is called an application. Applications is a property calculated for groups. The error occurred when the user was a member of the application group.

I assume that the deserializer is trying to deserialize the applications in front of the groups. He knew that there should be a member in the application array, but he did not have data from the groups.

In any case, since this is a computable property, it does not have business serialization, so to fix the problem, I added the [IgnoreDataMember] property to the property and it works like a charm!

+3
source

Source: https://habr.com/ru/post/1389432/


All Articles