DavidSpot Blog

Developer, super curious, a dog lover, sports fan and techie guy


Bypassing Web API JSON Property Length Limit

Did you haver encouter a weird bug while working with Web API like this: 

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

If you did, probably your next action was googling for a solution and very likely you stop in StackoverFlow with a lot's of answers. 

The most usual response to this issue it's to do one of three things

  • Go to Web.Config and change the proporty jsonSerialization maxJsonLength to the max value, witch is int.MaxValue like this
<configuration> 
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="50000000"/>
</webServices>
</scripting>
</system.web.extensions>
</configuration>

 

  • Add a special web.config key to appSettings:
<appSettings>
<add key="aspnet:MaxJsonDeserializerMembers" value="1000" />
</appSettings>

 

  • Or if you are using .NET MVC in a override de Json method in a controller
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonResult()
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior,
MaxJsonLength = Int32.MaxValue
};
}

 

The problem with all this solutions is none of them addresses the problem for a Web API. After a few time doing some tests I came up with a simple, yet hackie solution that looks like this:

[HttpGet]
//ResponseType it's for ApiDescription successfully generates the helper page with the right type since i'm returning a plain/text content
[ResponseType(typeof(YourType))]
public async Task<HttpResponseMessage> GetLargeJsonDataWithWebAPI()
{
    String url = "someUrl";
    String jsonData = EnvironmentUrlHelper.GetJsonResourseAsync<YourType>(url);


    var response = Request.CreateResponse();
    response.Content = new StringContent(JsonConvert.SerializeObject(rsp));

    return response;
}

What I'm doing is telling the Http that I'm not returning an application/Json result but instead a plain text (text/plain) witch is myobject serialized in JSON. By doing this we bypass the limit validation and can return large JSON data, though this is not recomended to do it's a nice way to play around with the framework.

In case you're asking what the hell his the attribute ResponseType, because I'm using the HelpPage nuget package, this enables the ApiDescription to resolve witch type the method returns.

Since I'm returning a HttpResponseMessage to do this bypass, if didn't use this attribute the HelpPage would use the for the return type the Type HttpResponseMessage instead of "YourType".

 


Top day-to-day C# 6 new features

As you are probably aware C# 6 is now available and there are some nice new additions to the language. Here is a quick glance at new features of C# 6 that I'm using most.

Auto-property initializers and read-only auto-properties

The previous versions of C# allowed you to create auto-properties like this:

public string Name { get; set; }

However, it wasn't possible to assign default value to the auto-property at the declaration line itself. In order to assign value you would use constructor like this:

public class Class1

{

      public string Name { get; set; }

      public Class1()

      {

         this.Name = "Janet";

      }

}

In C# 6 you can declare and initialize auto-properties at one go:

public string Name { get; set; } = "Janet";

Additionally, you can now create read-only auto-properties:

public string ID { get; }

Using static methods without class name qualifier

In order to use static methods exposed by a class you usually call them on the class they belong to. For example, to call WriteLine() method of Console class you would say:

Console.WriteLine("Hello World!");

In C# 6 you can use the using static statement to call the static methods without any class name qualifier. The following code fragment will make it clear:

using static System.Console;

 

namespace Namespace1

{

    public class Class1

    {

        public void Method1()

        {

            WriteLine("Hello World!");

        }

    }

}

 

 

Notice that the using static statement at the top specifies the fully qualified class name whose static methods are to be called. Then you can call WriteLine() without any class qualifier.

Null-conditional operators

Checking for null value is a very common (and annoying) operation. In earlier versions of C# you would typically do that like this:

public void Method(List<string> data)

{

    int i;

    if (data != null)

    {

        i = data.Count();

    }

}

In C# 6 there is a shortcut to null checking. The same task can be accomplished like this:

public void Method(List<string> data)

{

    int count = data?.Count() ?? 0;

}

Here, the ?. operator (null propagation operator) checks whether data is null. The Count() is called on data only if data is not null. Optionally you can also specify a value to be returned if data is null. This is done using ?? operator (null-coalescing operator). So, in the above example if data is null count variable will be 0, otherwise count will hold the number of elements in the List.

String interpolation

In the previous versions of C# you used String.Format() to format strings. In C# 6 you have an additional way to format your string data - string interpolation. Here is how you can use this feature:

string str = $"Today is {DateTime.Now:dd-MM-yyyy}";

Notice the use of $ before the string. The string has embedded place holder in the form of { }. The value of each place holder is specified directly inside { and }. You can also apply standard .NET formatting options to the value. So, in the above example the value of DateTime.Now is outputted in dd-MM-yyyy format.

nameof expression

In some cases you need the literal names of variables, properties, methods or classes. For example, while throwing ArgumentNullException you need to pass name of a parameter that caused the trouble. You can use hard-coded string names but there are chances of errors (for example, spelling mistakes).

In C# 6 you can use nameof expression to get the literal name of a variable, property, method or class. Here is how it can be used :

void test()

{

    Console.WriteLine("To get current date and time use "

        + nameof(DateTime.Now)

        + " methood of " + nameof(DateTime));

}

The first call to nameof returns string Now and the second nameof returns string DateTime.

Exception filters

Have a look at the following code:

public void Method(int i, int j)

{

    try

    {

        int k = i / j;

    }

    catch (DivideByZeroException)

    {

        Console.WriteLine("Divide by zero exception!");

    }

}

The catch block is going get executed whenever j is zero. What if you wish to execute the catch block only when certain condition is true. Say for example, you are storing some configuration setting and based on its value you wish to decide whether exception is to be handled or not.

In C# 6 you can apply exceptions filters like this:

public void Method5(int i, int j)

{

    try

    {

        int k = i / j;

    }

    catch (DivideByZeroException) when (HandleErrors)

    {

        Console.WriteLine("Divide by zero exception!");

    }

}

Here, the catch block is executed only when the expression in the when() evaluates to true. In the above example HandleErrors is a boolean property that governs whether errors are to be handled or not. if HandleErrors is set to true only then the catch block will be executed, not otherwise.