I have a fairly simple WCF service running as a Windows service with a WSHttpBinding and being consumed by a website. The service works, most of the time. Sometimes I get the following error when calling various methods on the 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 have stepped through in the debugger and the return results of the functions looks correct. I'm pretty new to WCF and have no idea what could be causing this error to know where to start looking for problems.
Any help greatly appreciated and I can provide more info if needed.
Update 2 - I have resolved this issue and will answer below.
Update
Service contract
[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;
}
}
The distribution group object has a few string properties and a List<User>. I've commented out setting these properties and the error persists, so I dont believe the problem lies in these objects.
Service bindings 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 am getting this error for a range of methods on my service and all of these methods have worked and are still working for some cases. The error occurs on service methods that have a void return type - so I don't think it is complaining about the data being returned by the service.