Announcement

Thursday, 4 December 2014

Json Size Limit

json size limit techiners
This post will highlight a very common error that comes often when we visit a webpage/website that uses AJAX. We know that in AJAX we have anonymous functions like: success, error etc. success gets called when our ajax request gets successfully completed and it returns a response whereas error gets called when ajax encounters a problem in processing a request.


Let us consider an example:

We have a table say Graphics with following fields-

GraphicsId
GraphicsName
GraphicsLayerId
GraphicsModeId
GraphicsDuration
StartDate
EndDate
IsBilled
AgencyCode
ClientCode
CreatedBy
CreatedDate
ModifiedBy
ModifiedDate
GraphicsCategoryId
GraphicsCode
TickerText

Let us assume that the table contains millions of graphics.

Now, our task is to fetch all those graphics for which the Selected Date lies in between StartDate and EndDate of the Graphics. So, we fetch these graphics using AJAX and LINQ.

So how we are going to achieve this?

Step 1 : First we call our method GetGraphics(DateTime SelectedDate) in the controller Graphics using AJAX and pass the selected date to this method as data. Note that the type will be POST, dataType as json, and contentType as application/json.

So the code will be like this:

$.ajax({
url: '@Url.Action("GetGraphics", "Graphics")',
data: JSON.stringify({ SelectedDate: $('#selectDate').val() }),
dataType: 'json',
type: 'POST',

contentType: 'application/json',
async: false,
success: function (graphics) {

    for (var i = 0; i < graphics.length; i++) {
        $("#tblGraphics").append("<tr style='background-color:#abcdef;font-weight:normal;         font-size:12px; white-space:nowrap;'><td>" + graphics[i].Name + "</td><td>"+ v           graphics[i].Template + "</td><td>" + graphics[i].Duration + "</td><td>" +                 graphics[i].Layer + "</td><td><select name='test' id='H" + graphics[i].Id + "'           class='hour'>"+ "</select><select name='test' id='M" + graphics[i].Id + "'               class='minutes'></select><select name='test' class='seconds' id='S" +                     graphics[i].Id + "'></select>" + "<select name='test' id='F" + graphics[i].Id +           "' class='frames'></select></td></tr>");
     }
},
error: function( jqXHR, textStatus, errorThrown) { alert(textStatus+ ' ' +jqXHR.status+' '+errorThrown); };
}
});

Step 2 : Now, we need to code for Json Method that will be called i.e., GetGraphics(). Within this method we first fetch all the graphics using LINQ and then iterate over these graphics using foreach loop. Within this loop, we fetch graphicsStartDate and graphicsEndDate and then comparing the SelectedDate with graphicsStartDate and graphicsEndDate, if SelectedDate lies with in the range than add the graphics in the list.

Code:

public JsonResult GetGraphics(DateTime SelectedDate)
{
GraphicsEntities context = new GraphicsEntities();
var allGraphics = context.Graphics.ToList();
List<GraphicsMaster> graphics = new List<GraphicsMaster>();

foreach (var g in allGraphics)
{


/* Check for dates: if graphicsEndDate<than selected Date than display graphics * i.e., add graphics into the list. If graphics end date is greater than selected date than don't add the graphics into the list. */

DateTime graphicsEndDate = Convert.ToDateTime(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).Select(b => b.EndDate).SingleOrDefault());
DateTime graphicsStartDate = Convert.ToDateTime(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).Select(b => b.StartDate).SingleOrDefault());

/* check whether selected date lies between graphics start date and graphics end date or not. If yes then get all the graphics for the selected date. Else get none. */


if (DateTime.Compare(SelectedDate, graphicsEndDate) <= 0 && DateTime.Compare(SelectedDate, graphicsStartDate) >= 0)
{
graphics.Add(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).SingleOrDefault());
}
}

try
{
var result = (from x in graphics select new { Id = x.GraphicsId, Name = x.GraphicsName, Template = x.GraphicsCode, Duration = x.GraphicsDuration, Layer = x.GraphicsLayerId });

//var result = new { Id = graphicsIds, Mode = graphicsModeNames, Graphics = graphics };


var jsonResult =Json(result, JsonRequestBehavior.AllowGet);


//jsonResult.MaxJsonLength = int.MaxValue;


return jsonResult;


}
catch{
       throw;
}
}

Step 3 : Notice that in AJAX success method when we are appending the rows to table the table id is tblGraphics. When we run our code, it will run successfully but no rows will get appended to the table. The reason is our AJAX success method does not get invoked. Instead, error method get called. In error method we just display the textStatus, jqXHR.Status, and errorThrown which will display the following alert as error 500 Internal Server Error.

Step 4 : It is because we are returning large number of records from the controller's GetGraphics() method which the Json is not capable of. There is nothing wrong at the client side. So, we need to increase the size of the Json that is returned from the GetGraphics() method. To do so, just remove the comments from the commented line in the GetGraphics() method.

So, the final code will look like this:

public JsonResult GetGraphics(DateTime SelectedDate)
{
GraphicsEntities context = new GraphicsEntities();
var allGraphics = context.Graphics.ToList();
List<GraphicsMaster> graphics = new List<GraphicsMaster>();

foreach (var g in allGraphics)
{

/* Check for dates: if graphicsEndDate<than selected Date than display graphics * i.e., add graphics into the list. If graphics end date is greater than selected date than don't add the graphics into the list. */

DateTime graphicsEndDate = Convert.ToDateTime(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).Select(b => b.EndDate).SingleOrDefault());
DateTime graphicsStartDate = Convert.ToDateTime(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).Select(b => b.StartDate).SingleOrDefault());

/* check whether selected date lies between graphics start date and graphics end date or not. If yes then get all the graphics for the selected date. Else get none. */


if (DateTime.Compare(SelectedDate, graphicsEndDate) <= 0 && DateTime.Compare(SelectedDate, graphicsStartDate) >= 0)
{
graphics.Add(context.Graphics.Where(b => b.GraphicsId == g.GraphicsId).SingleOrDefault());
}
}
try
{
var result = (from x in graphics select new { Id = x.GraphicsId, Name = x.GraphicsName, Template = x.GraphicsCode, Duration = x.GraphicsDuration, Layer = x.GraphicsLayerId });

var result = new { Id = graphicsIds, Mode = graphicsModeNames, Graphics = graphics };

var jsonResult =Json(result, JsonRequestBehavior.AllowGet);

jsonResult.MaxJsonLength = int.MaxValue;

return jsonResult;

}
catch{
       throw;
}
}

Step 5 : Notice that we have set the size of Json to the maximum value of int.

CONCLUSION


In this post we have seen how to eradicate Internal Server Error. Just we need to increase the size of Json and we are done. BEWARE! Some people say that Json has infinite limit, which is not the case always. It depends on servers. Most servers has configurable limit.

FEEDBACK

Hope the post will be useful for you in your programming career. What I need from you is to comment below and share with me your doubts and/or suggestions. Thank you :) Have a wonderful programming.

No comments: