When ever you need to send lots of lots of data in WCF REST service using custom SharePoint MultipleBaseAddressWebServiceHostFactory then you will encounter following error
(400) HTTP Bad Request
When you look into service trace you will find the actual root cause of this issue is that the data sent is not supported by default and its failing internally in deserialize process
<ExceptionType>System.ServiceModel.Dispatcher.NetDispatcherFaultException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:ADXML. The InnerException message was 'There was an error deserializing the object of type System.String. 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.'. Please see InnerException for more details.</Message>
<StackTrace>
Now if you try to override the settings in web.config then web service will complain about multiple settings for the same end point because factory it self creates the dynamic end points so web.service changes can't be used unless you remove the factory class and do it conventional way.
So what is the solution :
Its easy that we need to just extend two classes
Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory
Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHost
public class CustomMultipleBaseAddressWebServiceHostFactory : Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory
{
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new CustomMultipleBaseServiceHost(serviceType, baseAddresses);
}
}
public class CustomMultipleBaseServiceHost : Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHost
{
public CustomMultipleBaseServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
base.OnOpening();
System.Diagnostics.Debug.Assert(false);
foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
{
Binding binding = endpoint.Binding;
if (binding is WebHttpBinding)
{
var web = binding as WebHttpBinding;
web.MaxBufferSize = Int32.MaxValue;
web.MaxReceivedMessageSize = Int32.MaxValue;
}
var myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
}
}
}
Now if you see we can make the changes to any parameters like maxBufferSize or MaxrecievedMessageSize at the time of opening of channel.
Now instead of using default Microsoft class in the svc file we will use our custom dll reference. Deploy your solution. DO an IISRESET and you will be able to transmit huge data now :)
<%@ ServiceHost Language="C#"
Service="Custom.Assembly.Classname,$SharePoint.Project.AssemblyFullName$"
CodeBehind="CustomClass.cs"
Factory="CustomMultipleBaseAddressWebServiceHostFactory, $SharePoint.Project.AssemblyFullName$" %>
Gday,
ReplyDeleteYour code works beautifully.
I was getting the following exception trying to upload a file using the default 'Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory':
System.ServiceModel.ProtocolException: The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
I am not sure about the last part of your code where you are setting maxstringcontentlength?
I was able to upload large files without this being set. And also, why not just set it directly off your 'WebHttpBinding' object?
Thanks!
Peter
Peter,
ReplyDeleteYou can skip that part. Just a precaution to handle bad request.
Nitin
You rock!!
ReplyDeleteThank you so very much... worked for me :D
ReplyDelete