max Form Data length

Topics: Web Api
Apr 25, 2012 at 6:34 PM

Hello,

First, I'm using WCF Web API Preview 6.

I'm making XmlHttpRequests via jquery $.ajax to an IIS server hosting the WCF Web API.  The request looks like this from the Chrome 'Network' development tool:

Request URL:https://www.mymachine.com/MyApp/Resources/Document
Request Method:PUT
Status Code:200 OK

Request Headers:

Accept:application/json, text/javascript, */*; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:32774
Content-Type:application/x-www-form-urlencoded
Host:www.mymachine.com
Origin:https://www.mymachine.com
Referer:https://www.mymachine.com/MyApp/clipboard.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19
X-Requested-With:XMLHttpRequest

Form Data:

Category:null
... lots of stuff here ...
Type:Skilled Nurse Start of Care
UserId:29
VisitId:

Notice the the Content Type is

application/x-www-form-urlencoded

I've been using this because it seemed to be the only way to get a json object to serialize automatically from the javascript.  I'm not sure if there is a better way to do this.  That's the first question.

However, using the default configurations for the routes, it turns out that this data content is cut off at 32768 (32KB).  So I tried upping the MaxReceivedMessageSize and the MaxBufferSize in the configuration, but that had no effect.  This is the config from Global.asax.cs:

	void Application_Start(object sender, EventArgs e)
        {
            try
            {
                // Use MEF for providing instances
                //var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
                var catalog = new DirectoryCatalog("bin");
                var container = new CompositionContainer(catalog);
                //VerifyComposition(catalog, container);
                var config = new MefConfiguration(container);

                config.MaxReceivedMessageSize = int.MaxValue;
                config.MaxBufferSize = int.MaxValue;
                //config.TransferMode = System.ServiceModel.TransferMode.Streamed;

                logger.InfoFormat("MaxReceivedMessageSize = {0}", config.MaxReceivedMessageSize);
                logger.InfoFormat("MaxBufferSize = {0}", config.MaxBufferSize);
                logger.InfoFormat("TransferMode = {0}", config.TransferMode);

                config.Security = (uri, binding) =>
                {
                    if (uri.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase))
                        binding.Mode = HttpBindingSecurityMode.Transport;
                    else
                        binding.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
                };

                RouteTable.Routes.SetDefaultHttpConfiguration(config);

                RouteTable.Routes.MapServiceRoute<MyCompany.Blah.Resources.PocResources>("Resources", config);
                logger.Info("The HTTP resource 'Resources' was created successfully.");
            }
            catch (Exception ex)
            {
                logger.Error("There was an error when creating the HTTP resource 'Resources'", ex);
                throw;
            }
        }

This is the service method from MyCompany.Blah.Resources.PocResources:

	[WebInvoke(UriTemplate = "Document", Method = WebMethods.Put)]
        public DocumentSaveResponse SaveDocument(DocumentDto document)
        {
           // My method code...
        }

The 'document' object does not get deserialized properly if the content of the request is larger than 32768.  It just gets cut off but does not throw an error and simply fills in whatever it can based on the size.  The document object has a DocumentData content which is a JSON string.  Since it seems to deserialize in alphabetical order of the properties of the DocumentDto class, the data for the latter properties are either completely missing or cut off depending on how large the JSON string is for DocumentData.

As you can see, setting the max message and buffer sizes did not help, nor did setting the TransferMode to Streamed.  At this point, I'm not sure how to handle larger message data.  Any suggestions would be very helpful.  Thanks.

 

Apr 25, 2012 at 10:25 PM

After digging into the source code and doing a lot of debugging, I found that the FormUrlEncodedFormatter.ReadBufferSize was defaulting to 32768.  So, I set it to a larger value when the 'config' is defined (in the previous post), like so:

 

var formUrlEncodedFormatter = config.Formatters.FormUrlEncodedFormatter;
if (formUrlEncodedFormatter != null)
{
    formUrlEncodedFormatter.ReadBufferSize = 1024 * 1024 * 10;  // 10 MB
    logger.InfoFormat("FormUrlEncodedFormatter.ReadBufferSize = {0}", formUrlEncodedFormatter.ReadBufferSize);
}

 

Coordinator
Apr 25, 2012 at 11:19 PM

Please note that WCF Web API has been replaced by ASP.NET Web API. We recommend that you update to using the new bits at your earliest convenience. Thanks.

Daniel Roth