I have a very strange situation. I have a large set of records to return as a List from a WCF service. If I return the set as a DataTable, everything works fine. There are about 19,000 records in the set. If I return the set as a List (where T is a DataContract) it errors out and closes connection upon returning any set longer than 10922 records. I would think it was a problem with my data except another person has reported the exact same problem with a limit of 10922 records. Has anyone else encountered this problem, and if so how did you solve it?
We encountered the same problem.
From the service trace log we could retrieve the following exception:
Error while trying to serialize parameter []. Maximum numberError while trying to serialize parameter []. Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota.
After changing the dataContractSerializer key with parameter maxItemsInObjectGraph everything was running smoothly even with millions of records (on condition that you changed the maxReceivedMessageSize accordingly).
These changes have to be made in the web.config and the app.config in the following way:
web.config:
<behaviors>
<serviceBehaviors>
<behavior name="WasteWatcher.TestService.ServiceImplementation.TestService_Behavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
app.config:
<behaviors>
<endpointBehaviors>
<behavior name="SerializerBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
Don't forget to add the parameter behaviorConfiguration="SerializerBehavior" to the endpoint key:
<endpoint address="http://localhost:9542/TestService.Host/TestService.svc"
binding="customBinding" bindingConfiguration="DefaultEndpoint"
contract="WasteWatcher.TestService.Test.Client.TestServiceProxy.TestServiceContract"
name="DefaultEndpoint" behaviorConfiguration="SerializerBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
Best regards
Markus Rohlof
Check your endpoints' maxReceivedMessageSize on both client and server.
We actually have this problem at work. We try to send a lot of data through a WCF web service. We get cutout at something like 20,000 records so we ended up breaking up the data and doing a number of web service calls. Can you do something similar? Break up the records into smaller chunks and then merge them on the other end?
Related
The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'PostTransaction'. The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 52
You need add this argument to your config, like
<bindings> <webHttpBinding> <binding> <readerQuotas maxStringContentLength="65535"/> </binding> </webHttpBinding> </bindings>
Exaple from this answer: Fixing maximum length quota on XmlDictionaryReaderQuotas for WCF 4.0 REST
I have a WCF SOAP Service with about 100 functions. I only want to expose some of them to REST endpoints. Isnt it possible to do this with only one contract?
I added a rest behavior and rest endpoint like this:
<behaviors>
<endpointBehaviors>
<behavior name="RestBehavior">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"/>
</behavior>
</endpointBehaviors>
</behaviors>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration ="RestBehavior" contract="Test.IService" />
<endpoint address="" binding="customBinding" bindingConfiguration="BufferedHttpBinaryBusiness"
bindingName="BufferedHttpBinaryBusiness" contract="Test.IService" />
and added WebGet attribute to the function I want to expose on rest endpoint:
<WebGet(BodyStyle:=WebMessageBodyStyle.Wrapped, RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json, UriTemplate:="/IsRegistered?Id={Id}")>
<ServiceModel.OperationContract()>
Function IsRegistered(ByVal Id As String) As Boolean
But I also have my other functions which I dont want to expose as REST.
<ServiceModel.OperationContract()>
Function GetName(ByVal x As Long, ByVal y As String) As String
<ServiceModel.OperationContract()>
Function GetId(ByVal name As String) As String
The error I got is:
System.InvalidOperationException: Operation 'GetName' of contract 'IService' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.
at System.ServiceModel.Description.WebHttpBehavior.TryGetNonMessageParameterType(MessageDescription message, OperationDescription declaringOperation, Boolean isRequest, Type& type)
at System.ServiceModel.Description.WebHttpBehavior.ValidateBodyStyle(OperationDescription operation, Boolean request)
at System.ServiceModel.Description.WebHttpBehavior.<>c__DisplayClass10.<>c__DisplayClass13.<GetRequestDispatchFormatter>b__d()
at System.ServiceModel.Description.WebHttpBehavior.<>c__DisplayClass10.<GetRequestDispatchFormatter>b__c()
at System.ServiceModel.Description.WebHttpBehavior.HideReplyMessage(OperationDescription operationDescription, Effect effect)
at System.ServiceModel.Description.WebHttpBehavior.GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
at System.ServiceModel.Description.WebHttpBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
at System.ServiceModel.ServiceHostBase.InitializeRuntime()
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)
When I add WebGet attribute to this function, then the same error happens for another soap function. It seems that it requires me to apply WebGet attribute to all functions. In other words, it requires me to expose all functions in contract to expose to REST endpoint. But I want only some of them to expse as REST. Isnt it possible?
In short, no. You must have two different contracts to get both SOAP and REST to work together. You can add both endpoints in the same config though. The good thing is that you just need to define the REST operations in a separate interface/contract and have you service inherit from that interface as well, and you don't have to change your code.
The article below is a great explaination, and way to implement both in your service. I used this as an example in two of my own services that I wrote.
How to enable REST and SOAP both on the same WCF service
I get an exception when there are too many objects returned:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://.../Contract:GetBlaBlaResult. The InnerException message was 'Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota. '. Please see InnerException for more details.
I’ve looked it up and added under behaviors in the server side:
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
...
And in the client side:
<behaviors>
<endpointBehaviors>
<behavior name="maxItems">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
But it seems that it is ignored and the exception keeps arising.
The thing is I use XmlSerializer (for attributes in the elements):
[ServiceContract(Namespace = "http://BlaBla.com/webservices/BlaBlaService")]
[XmlSerializerFormat(SupportFaults = true)]
public interface IBlaBlaServices
{
[OperationContract]
BlaBlaResponse GetBlaBla(BlaBlaRequestMessage searchBlaBlaRequest);
}
and the exception, as you can see, refers to the dataContractSerializer (and so is the configuration I’ve added above).
Is it the XmlSerializer that mess up the things?
Can somebody advise please?
Thanks a lot :)
Just to make sure, are you applying the MyServiceBehavior behavior to the service definition in the service config and the maxItems behavior to the endpoint definition in the client config (the behaviorConfiguration attribute)?
This one has me puzzled and am hoping it's a silly oversight on my part. When I call the following web service, if a null parameter is encountered then all following parameters are null (or zero for the numerics).
[OperationContract, ProtoBehavior]
[ServiceKnownType(typeof(ServiceFault))]
[FaultContract(typeof(ServiceFault))]
PersonProfileMessagePart Create(ObjectId person, ObjectId industry, int yearsInIndustry, ObjectId occupation, string occupationFreeText,
int yearsInOccupation, string maritalStatus, string educationLevel,
List<ChildMessagePart> children, FinancialProfileMessagePart financialProfile,
List<ObjectId> traits);
For example, if person and yearsInIndustry are present but not industry, all parameters including yearsInIndustry default to null/zero. Is there an additional attribute I need to apply?
{edit}
My bad. Marc, it is WCF with a custom binding.
<customBinding>
<binding name="ServiceFedBinding">
<security authenticationMode="SecureConversation">
<secureConversationBootstrap authenticationMode="IssuedToken">
<issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<issuer address="http://links-dev:91/security/authentication/securetokenservice.svc/" binding="wsHttpBinding">
<identity>
<dns value="LINKS"/>
</identity>
</issuer>
<issuerMetadata address="http://links-dev:91/security/authentication/securetokenservice.svc/mex"/>
</issuedTokenParameters>
</secureConversationBootstrap>
</security>
Thanks in advance.
Mike
my WCF service it's used by a Silverlight application to retrieve data. I've no problem,
[OperationContract]
MyCollectionClass GetList(int sessID, string name);
[CollectionDataContract]
public class MyCollectionClass : List<MyClass>{ }
[DataContract]
public class MyClass {
[DataMember]
public string Prop1 { get; set; }
[DataMember]
public string Prop2 { get; set; }
}
But.. when MyCollectionClass have a less then 3000+ "record" it works. When the number of records is greater the WCF service seems to work, but on the completed event of the Silverlight app an exception occurs: "Service Not Found".
I've found that could be related to service configuration and i've tryied to use both:
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
on WCF and Client configuration. Also added:
readerQuotas:
maxArrayLength="2000000"
maxStringContentLength="2000000"/>
(also changed the values found) But seems to not working.
I think that the problem is that the message exceed the max number of byte per "message", but I do not understand why data is not spanned on different message. Any tips is appreciated.
Giorgio
I had the same problem, in my case was just serializing an string and no prob there, BUT in your case you are serializing a big bunch of objects, there's a default limit for that, I remember I saw a post about that (just a setting in the config --> maxItemsInObjectGraph) to high up that number of serialized objects,
Links
http://silverlight.net/forums/t/17674.aspx
http://forums.asp.net/t/1330713.aspx
Settings:
HTH
Braulio
Try to enable wcf service logging on server side. This might help: http://msdn.microsoft.com/en-us/library/ms730064.aspx
I use these 2 statement right after InitializeComponent:
binding.MaxReceivedMessageSize = 5000000
binding.MaxBufferSize = 5000000
You can change the numbers to what you want but I had to do this in order to recieve a large amount of data on the Silverlgiht client. My binding object is defines as:
Private binding As New BasicHttpBinding
This is in vb.net. Works like a charm after I include these items.
I would take a look at http://smehrozalam.wordpress.com/2009/01/29/retrieving-huge-amount-of-data-from-wcf-service-in-silverlight-application/.
I use silverlight 4 and vs 2010, and I had the same problem, and I resolved modifing the web.config file.
My original web.config file had:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
And I changed it by:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/> <!--this very is important: it is the size of the buffer-->
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Could I suggest that you decrease the number of records you are returning? Not as a work around but as a usability suggestion. I cannot imagine any user coping with being shown 3000+ records. If you will be aggregating values from the data set rather aggregate them server side, it will boost your app's performance greatly... I have encountered this a couple of times in my apps, and almost always it worked out better to change the design than the options...