find a location for property in a new city

Tuesday 27 March 2012

Reuse Select function in Linq

You can reuse Linq Select functions by defining a delegate Func field that can be used in multiple Linq queries.

I had a few Linq to Objects queries that were querying the same collection but had different Where clauses that were nested between various if statements. The similarity between all of these statements was the Select function. This was quite long itself and it was annoying seeing such repetition. DRY!

So I tried to create a Func parameter that I could just pass into my Select statement which previously, for example could look like this:

ReturningPerson person;
if (iFeelLikeIt)
{
    person = people.Where(person => person.IsNameFunny)
                .Select(person =>
                    new ReturningPerson
                    {
                        DateOfBirth = input.DateBorn,
                        Name = string.Format("{0} {1}",
                            input.FirstName, input.LastName),
                        AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder",
                        CanFlyJet = false
                    })
                .FirstOrDefault();
}
else
{
    person = people.Where(person => person.Toes == 10)
                .Select(person =>
                    new ReturningPerson
                    {
                        DateOfBirth = input.DateBorn,
                        Name = string.Format("{0} {1}",
                            input.FirstName, input.LastName),
                        AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder",
                        CanFlyJet = false
                    })
                .FirstOrDefault();
}

This could be modified to work like this:

Expression<Func<InputPerson, ReturningPerson>> selector = (input) =>
    new ReturningPerson
    {
        DateOfBirth = input.DateBorn,
        Name = string.Format("{0} {1}",
            input.FirstName, input.LastName),
        AwesomenessLevel = input.KnowsLinq ? "High" : "Must try harder",
        CanFlyJet = false
    };
ReturningPerson person;
if (iFeelLikeIt)
{
    person = people.Where(person => person.IsNameFunny)
                .Select(selector)
                .FirstOrDefault();
}
else
{
    person = people.Where(person => person.Toes == 10)
                .Select(selector)
                .FirstOrDefault();
}

Follow britishdev on Twitter

Tuesday 13 March 2012

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

Whilst creating a JsonResult for my web service in ASP.NET MVC I received a deserialisation error of type "InvalidOperationException" with the description "Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property."

In fairness I was sending quite a large JSON object at the time, largely due to there being 288 base64 embedded images totally ~15MB I'd guess... Whoops! Anyway, it may be a hilariously large amount of data but it is what I want so how to work around this?...

There is a web config setting that can resolve this which was my first discovery in my path to success:

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

This is the official word from Microsoft about this but unfortunately this only works when you are specifically serialising (or deserialising) things yourself. This has no relation on the inner workings of the framework such as my bit of MVC code which is currently as follows:

public JsonResult GetData()
{
    return Json(GetCrazyAmountOfJson(), JsonRequestBehavior.AllowGet);
}

So for those of you using the Json() method in ASP.NET MVC or some other similar .NET framework voodoo like me the work around is to write your own code and bypass the framework such as:

public ContentResult GetData()
{
    var data = GetCrazyAmountOfJson();
    var serializer = new JavaScriptSerializer();
    serializer.MaxJsonLength = int.MaxValue;
    var result = new ContentResult();
    result.Content = serializer.Serialize(data);
    result.ContentType = "application/json";
    return result;
}

The MaxJsonLength is an Int32 so the maximum length can only be the maximum int value (1.4billion or something), you cannot make it unlimited. I assume this limit is here to make you think twice before making crazy big JSON serlisations. Did it?

Follow britishdev on Twitter