Solved

maxJsonLength exceeded error on ajax Post to ASP.NET MVC Controller Action method

Posted on 2016-11-15
5
53 Views
Last Modified: 2016-11-17
I am getting the following error when my javascript attempts to execute the SaveUserCostCentreList MVC Controller Action using $.ajax Post.  The error gets displayed before I can step into the method on the Server Controller.

Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.
Parameter name: input


I have tried setting the maxJsonLength property and other properties relating to data sizes within the web.config but nothing works.

Server side, client side and web config snippets are listed below.


SERVER SIDE

[HttpPost]
        public ActionResult SaveUserCostCentreList(UserVM userVm)
        {
           // error message is displayed without this ever getting executed
           // do stuff with userVm

        }

Open in new window


CLIENT SIDE

 $.ajax({
          url: '@Url.Action("SaveUserCostCentreList", "Admin")',
          data: jsonString,
          type: 'POST',
          contentType: 'application/json',
          dataType: 'json',
           success: function (result) {
                   alert('ok');
               }
          }); 

Open in new window



WEB.CONFIG entries

 <system.web>
    <httpHandlers />
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5">
      <assemblies>
        <add assembly="Microsoft.Build.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
        <add assembly="System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
     </assemblies>
      <buildProviders />
    </compilation>
    <httpRuntime maxRequestLength="2000000000" />       
  </system.web>

  <system.web.extensions>
    <scripting>
      <webServices>
        <jsonSerialization maxJsonLength="2147483647">
        </jsonSerialization>
      </webServices>
    </scripting>
  </system.web.extensions>

  <system.webServer>
    <httpProtocol />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="10485760" />
      </requestFiltering>
    </security>
  </system.webServer>

Open in new window

0
Comment
Question by:ccravenbartle
  • 2
  • 2
5 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41888231
Have you tried this
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.MaxJsonLength = int.MaxValue;
...
return jss.Serialize(yourDataObject);.

Open in new window

0
 

Author Comment

by:ccravenbartle
ID: 41888301
Hi Julian  - thank you for your quick response.

Please clarify.   Is this code which I have to add to the server Controller SaveUserCostCentreList method?  I am uploading my json object view model to the controller using POST,  Is this not applicable to server Get requests rather than server Post requests?  

JavaScriptSerializer jss = new JavaScriptSerializer();
jss.MaxJsonLength = int.MaxValue;
...
return jss.Serialize(yourDataObject);.

Charles
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41888312
Are you getting the error on the upload - I thought it was the download - did not read the question properly.

What does your .Net service code look like?
0
 

Author Comment

by:ccravenbartle
ID: 41888323
Yes, it is on the upload.  The method call works fine if I chop the data in half so I know there is nothing wrong with the Controller Action method itself.

[HttpPost]
         public ActionResult SaveUserCostCentreList(UserVM userVm)
         {
            // error message is displayed without this ever getting executed
            // do stuff with userVm

         }
0
 
LVL 82

Accepted Solution

by:
leakim971 earned 500 total points
ID: 41888685
We use this file to create a custom JsonValueProviderFactory :
We need to change MaxJsonLength property
From here it is set by default to 2097152 (2*1024*1024 = 2MB), check line 50 :

CustomJsonValueProviderFactory.js :
using System.Web.Mvc;

namespace YourNameSpace
{
    public sealed class CustomJsonValueProviderFactory : ValueProviderFactory
    {
        private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
        {
            IDictionary<string, object> d = value as IDictionary<string, object>;
            if (d != null)
            {
                foreach (KeyValuePair<string, object> entry in d)
                {
                    AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value);
                }
                return;
            }

            IList l = value as IList;
            if (l != null)
            {
                for (int i = 0; i < l.Count; i++)
                {
                    AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]);
                }
                return;
            }

            // primitive
            backingStore.Add(prefix, value);
        }

        private static object GetDeserializedObject(ControllerContext controllerContext)
        {
            if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            {
                // not JSON request
                return null;
            }

            StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            string bodyText = reader.ReadToEnd();
            if (String.IsNullOrEmpty(bodyText))
            {
                // no JSON data
                return null;
            }

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.MaxJsonLength = int.MaxValue;

            object jsonData = serializer.DeserializeObject(bodyText);
            return jsonData;
        }

        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            object jsonData = GetDeserializedObject(controllerContext);
            if (jsonData == null)
            {
                return null;
            }

            Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            EntryLimitedDictionary backingStoreWrapper = new EntryLimitedDictionary(backingStore);
            AddToBackingStore(backingStoreWrapper, String.Empty, jsonData);
            return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
        }

        private static string MakeArrayKey(string prefix, int index)
        {
            return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
        }

        private static string MakePropertyKey(string prefix, string propertyName)
        {
            return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName;
        }

        private class EntryLimitedDictionary
        {
            private static int _maximumDepth = GetMaximumDepth();
            private readonly IDictionary<string, object> _innerDictionary;
            private int _itemCount = 0;

            public EntryLimitedDictionary(IDictionary<string, object> innerDictionary)
            {
                _innerDictionary = innerDictionary;
            }

            public void Add(string key, object value)
            {
                if (++_itemCount > _maximumDepth)
                {
                    throw new InvalidOperationException(MvcResources.JsonValueProviderFactory_RequestTooLarge);
                }

                _innerDictionary.Add(key, value);
            }

            private static int GetMaximumDepth()
            {
                NameValueCollection appSettings = ConfigurationManager.AppSettings;
                if (appSettings != null)
                {
                    string[] valueArray = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers");
                    if (valueArray != null && valueArray.Length > 0)
                    {
                        int result;
                        if (Int32.TryParse(valueArray[0], out result))
                        {
                            return result;
                        }
                    }
                }

                return 1000; // Fallback default
            }
        }
    }
}
         

Open in new window

 

Open your Global.asax.cs to replace the default JsonValueProviderFactory by the custom one :

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            /
            foreach(var factory in ValueProviderFactories.Factories)
            {
                if(factory is JsonValueProviderFactory)
                {
                    ValueProviderFactories.Factories.Remove(factory as JsonValueProviderFactory);
                    break;
                }
            }
            ValueProviderFactories.Factories.Add(new CustomJsonValueProviderFactory());
        }

Open in new window

0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

I found this questions asking how to do this in many different forums, so I will describe here how to implement a solution using PHP and AJAX. The logical flow for the problem should be: Write an event handler for the first drop down box to get …
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now