1

In a web forms project, I am loading a jqGrid using a SQL stored procedure where I return the data as json. During initial setup and testing, I was returning 85 rows of data. I then changed the parameters which caused 1,868 rows to be returned, except it was not displaying in the grid.

Upon debugging in Firebug, I saw the error "The length of the string exceeds the value set on the maxJsonLength property". I fixed it by setting the maxJsonLength="2147483647" in my webconfig as found in a popular Stackovrflow post.

So my question is what was the string that caused the error? Is it the length of the whole data record, or the length of the data in one of the columns returned?

I've seen examples of the jqGrid returning much more data. Thanks for any insight.

Update

I took Olegs advice and used Nuget to install Newtonsoft.Json in my project. I then made changes to my code to use it:

In the codebehind - .cs I have this:

using Newtonsoft.Json;

public partial class Default2 : System.Web.UI.Page {

[WebMethod]
public static string GetDataFromDB()

{
    DataSet ds = new DataSet();


    string con = System.Configuration.ConfigurationManager.ConnectionStrings["SQLCon"].ToString();
    SqlConnection SCon = new SqlConnection(con);
    SCon.Open();
    SqlCommand sqlCmd = new SqlCommand("dbo.usp_GetProjectDetails", SCon);
    sqlCmd.CommandType = CommandType.StoredProcedure;

    sqlCmd.Parameters.Add("@ProjNum", SqlDbType.Int).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@TrakIt", SqlDbType.VarChar, 255).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@Title", SqlDbType.VarChar, 255).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@Status", SqlDbType.VarChar, 255).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@Dept", SqlDbType.Int).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@AssignTo", SqlDbType.Int).Value = DBNull.Value;  //19;
    sqlCmd.Parameters.Add("@RecDate", SqlDbType.DateTime).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@CmpDate", SqlDbType.DateTime).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@EndDate", SqlDbType.DateTime).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@ExComp", SqlDbType.Int).Value = DBNull.Value;
    sqlCmd.Parameters.Add("@ExAcReq", SqlDbType.Int).Value = DBNull.Value;

    SqlDataAdapter da = new SqlDataAdapter(sqlCmd);
    da.Fill(ds);
    SCon.Close();

    return JsonConvert.SerializeObject(ds.Tables[0]);
}

The function in .aspx looks like this:

    <script type="text/javascript">
    $(document).ready(function () {
        $.ajax({
            type: "POST",
            contentType: "application/json",
            data: "{}",
            url: "Default2.aspx/GetDataFromDB",
            dataType: "json",
            success: function (data) {
                data = data.d;
                $("#list1").jqGrid({
                    datatype: "local",
                        colNames: ["Project #", "Trak-It #", "Priority", "Title", "Status", "Department", "Assigned To", "Resource", "Requestor"],
                        colModel: [
                                          { name: 'Project Number', index: 'Project Number', width: 80, key: true, formatter: 'showlink', formatoptions: { baseLinkUrl: 'Details.aspx', target: '_new' } },
                                          { name: 'Trak-It #', index: 'Trak-It #', width: 80 },
                                          { name: 'Priority', index: 'Priority', width: 80 },
                                          { name: 'Title', index: 'Title', width: 200 },
                                          { name: 'Status', index: 'Status', width: 80 },
                                          { name: 'Department', index: 'Department', width: 180 },
                                          { name: 'Assigned To', index: 'Assigned To', width: 100 },
                                          { name: 'Resource', index: 'Resource', width: 160 },
                                          { name: 'Requestor', index: 'Requestor', width: 140 }
                        ],
                        data: JSON.parse(data),
                        rowNum: 8,
                        rowList: [10, 20, 30],
                        pager: '#pager1',
                        caption: "Test Grid",
                        viewrecords: true,
                        ignoreCase: true,
                        async: true,
                        loadonce: true,
                        gridview: true,
                        width: 1000
                });
            }
        });
    });

</script>

And finally in Web.config, I commented out the maxjsonLength:

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

But I still get the error = "Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property."

If I uncomment the web.config settings, it works just fine. If I leave it commented out and bring back less data, it works fine. What am I missing?

Guanxi
  • 3,103
  • 21
  • 38
Brian
  • 548
  • 2
  • 8
  • 22

1 Answers1

2

You mean probably System.Web.Script.Serialization.JavaScriptSerializer.MaxJsonLength property which need be increased globally if you use WebServices interface in the server code. The solution was described in the answer for example.

You ask about the background information of the problem. To tell the truth the main problem is that usage of very old WebService interface in ASP.NET applications. It was the first attempt by Microsoft, many years ago, to return XML or JSON data based on Content-Type header of HTTP request. It was implemented in .NET Framework 3.5. The web service should return object (not a string) which will be serialized by .NET framework to JSON string by usage of JavaScriptSerializer. Your code don't uses JavaScriptSerializer directly. Because you don't use JavaScriptSerializer directly, you can configure parameters of JavaScriptSerializer only in web.config.

In other words, you have to use MaxJsonLength settings of JavaScriptSerializer in web.config every time if the size of returned data could be larger as about 100k.

The restriction 100k for web method was relatively large 8 years ago (at 2007) at the time of publishing .NET Framework 3.5. Later Microsoft introduced WCF interface which made JSON serialization more quickly, and have not so small restriction. WCF is of case too old now too, but it allows still to make manual serialization using more performance version of JSON serializer (see the answer for example). After WCF Microsoft introduced ASP.NET MVC and then WebAPI. Now Microsoft works on ASP.NET 5 and MVC version 6, which combine MVC and WebAPI under one name MVC6. Starting with MVC2 (or MVC3) Microsoft stopped to develop own JSON serializer and suggested to use some other one. Microsoft use mostly Newtonsoft.Json (synonyme of Json.NET), which is not the most quick one, but relatively good and powefull.

I don't want to write too much too common things, but I would recommend you to go away from reto style of usage WebServices and go to some other interface which gives you more flefibility in choosing of JSON serializer. If you support some old code and can't use more modern technologies then I would recommend you to use ASHX handle, which are very old, but much more flexible as WebServices. I recommend you to look in the old answer, where I attached Visual Studio Project which used ASHX handle and return JSON data using Newtonsoft.Json (Json.NET). You can replace Newtonsoft.Json to any other JSON serializer class which you more like.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Oleg - thanks for the information, although I'm not sure I follow your last paragraph. I'm using web forms to take advantage of membership services, and am in need of a fixed header type grid to display results from a stored procedure - thus my usage of jqGrid. In my research on it, I actually downloaded your VS project, but it seemed a lot for what I needed to do. – Brian Nov 16 '15 at 11:44
  • Also, this is a new project, and am just starting to code in C#. So I take it that the answer is that there is a limitation on the amount of json data returned, and I could run into an issue with a large result set. – Brian Nov 16 '15 at 11:51
  • If you just starting to code in C# then I would recommend you to use ASP.NET MVC5 and implement the controller action, which just return **all data** returned from STORED PROCEDURE. You should just add `loadonce: true` jqGrid option. Then jqGrid will makes paging/filtering/sorting of all data **locally**. MVC5 uses `Newtonsoft.Json` by default if you just return `Json(listOfItems, JsonRequestBehavior.AllowGet)` from the controller action. Thus you need just prepare `List` from the results of call of STORED PROCEDURE. – Oleg Nov 16 '15 at 12:00
  • I used Nuget and installed Newtonsoft.Json. My stored procedure fills a datatable - dt, so I converted it to a json string by doing: string json = JsonConvert.SerializeObject(dt); Now I'm back to the drawing board with jqgrid, trying to display this. Not sure how to show code in comments on here. Thanks for the heads up on Newtonsoft.Json - I'll remove the max length from web.config – Brian Nov 16 '15 at 19:18
  • @Brian: You are welcome! Is jqGrid will be filled successfuly now with large data? If you need to post some code then you should do always the following: click "edit" link/button below the text of your question, append your text with words like **UPDATED:** or **UPDATED 2:** and then append any code or additional information, finally you should write short comment to inform other that you posted additional information at the end of the text of your question. – Oleg Nov 16 '15 at 19:34
  • No - not yet. My previous implementation was using the java serializers. I'm not much of a guru when it comes to this stuff - yet... Going to look at your example to see what it is doing with the json string data to display in jqgrid. – Brian Nov 16 '15 at 19:55
  • Oleg, took your advice, but get the same results. See update above. – Brian Nov 17 '15 at 14:52
  • @Brian: You should always post the code. I see your errors in 1 sec. The line `[WebMethod]` means that you misunderstood me. The next line `public static string GetDataFromDB()` shows one more error. I wrote you in my answer: "The web service should return object (not a string) which will be serialized by .NET framework to JSON string by usage of JavaScriptSerializer." Instead of the method `GetDataFromDB` return **string** instead of **object**. The returned string will be **additionally serialized to XML or JSON**. Thus you will have the same problem as before. – Oleg Nov 17 '15 at 16:24
  • @Brian: If you will continue to use `[WebMethod]` then the results returned from `GetDataFromDB` will be **always serialized using `JavaScriptSerializer`** which is slow and have the size restriction which one can increase only by including `maxJsonLength` in the `web.config`. Only because the results will be serailized to JSON **twice** you require to use `data: JSON.parse(data)` parameter of jqGrid. The first deserializing from JSON makes `$.ajax`, but the result `data.d` is still string and not object (bacause of `string GetDataFromDB()` instead of `object GetDataFromDB()`). – Oleg Nov 17 '15 at 16:30
  • @Brian: You can change `public static string GetDataFromDB()` to `public static object GetDataFromDB()` and change it's code to `return ds.Tables[0];` instead of `return JsonConvert.SerializeObject(ds.Tables[0]);`. After that you can use `data: data` instead of `data: JSON.parse(data)`. It would be the first step to clean you code. To solve your problem really you should **don't use `WebMethod` at all**. If you don't want/can to use more modern technologies then I recommend you to use at least ASHX handle which I referenced in my answer. Do you know how to add ASHX handle to existing project? – Oleg Nov 17 '15 at 16:35
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/95376/discussion-between-brian-and-oleg). – Brian Nov 17 '15 at 18:08
  • My hat is off to Oleg for patiently guiding me through a resolution to my jqGrid issue. Since the comments got too long, we ended up in a chat which he graciously accepted. – Brian Nov 18 '15 at 16:48