@Blog.Author(Nandip Makwana) .LearningExperience(ASP.NET, ASP.NET MVC, IIS, jQuery & Technology Surrounding it...)

June 16, 2013 comment , , , , ,

ASP.NET MVC View Model: Entity Framework & JSON Serialization

Many times I came across an ASP.NET MVC application, where Entity Framework Model (or Database Model) is being used as view model as well. No this post is not about to discuss whether entity model should be used as view model or not but in this post we will discuss one tip with respect to JSON Serialization which will help to improve performance in terms of CPU processing and bandwidth usage while using entity model as view model.

Before we get into implementation scenario, let me list down few points which leads to use entity model as view model. Once again please note that this post is not to discuss or justify whether entity model should be used as view model or not.

  • One argument I heard is that not in all cases but most of the time your view model would be almost ditto as entity model or database model and in such case why should we maintain another type for view model.
  • While we are maintaining separate type for view model, we need to convert entity model into view model each and every time view is rendered. Yes of course we can use AutoMapper or something similar mapper library for type mapping and conversion but still personally I believe why this extra overhead of type conversion?

So above is two major concern which leads to use entity model itself as a view model. So now we will try to understand whole scenario by formulating one example. Below is application/project setup.

  • MVC 3/4
  • Use of AJAX wherever possible for better user experience
  • Entity Framework with Entity Context or Entity Object (Default EDMX template with Visual Studio 2010, DbContext scenario is also covered later in this post)
  • Newtonsoft.Json for JSON Serialization

For this post demo we will use Northwind Database Category & Product table. Following is the diagram of Entity Designer with Category & Product table.

Entity Framework creates Navigation Properties for parent/child table. Now whenever we will try to serialize entity model it will also populate & serialize navigation properties. For better understanding consider the Category Listing page with paging which will refresh category list via AJAX call and server response is in JSON format. Look at the below two images.

As we can see that it is populating & serializing each navigation properties while in this specific scenario we are not going to use child record i.e. Products record. Along with child record it is also serializing details of Entity Keys for category have a look at below image.

In this specific case or most cases, we are not going to use child records or entity keys because most of the time our strategy would be on demand loading. And more importantly serialization of child records also leads to increases response size see marked box in above both images. Here there are two scope for improvements one Stop Serializing of Child Records to reduce response size. And eventually when we are omitting child records from serialization, it will reduce CPU processing as well. Before we look into actual implementation have a look at below image which shows response detail after optimization.

Voila we have reduced response size from 37.3 KB to 1.1 KB :) yes this is oblivious because in this case we are not serializing child records of entity framework model. In this demo post there are only 8 records in Category Table but consider real time application scenario where there can be few hundreds or more records. So below is the implementation for the same how we achieved this.

As earlier noted, we are using Newtonsoft.Json library for JSON serialization. To achieve above optimization in JSON serialization we have created custom JSON Converter by deriving Newtonsoft.Json.JsonConverter. Below is the actual implementation of custom JSON Converter.

public class EFNavigationPropertyConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        bool isValid = false;
 
        if (objectType.FullName == "System.Data.EntityKey")
            isValid = true;
 
        if (objectType.IsGenericType &&
            objectType.GetGenericTypeDefinition().FullName
            .Contains("System.Data.Objects.DataClasses.EntityCollection"))
        {
            isValid = true;
        }
 
        return isValid;
    }
 
    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        return existingValue;
    }
 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteNull();
    }
}

In above custom JSON converter we are checking if target object type is of EntityKey or EntityCollection then we are serializing NULL. That’s it and below is the code snippet of how to use this custom JSON converter with JSON.NET.

public ActionResult GetCategory()
{
    EF.EO.Northwind40Entities e = new EF.EO.Northwind40Entities();
 
    List<EF.EO.Category> categoryList = e.Categories.ToList();
 
    string strJSON = JsonConvert.SerializeObject(categoryList, 
        new EFNavigationPropertyConverter());
            
    return Content(strJSON, "application/json");
}

Entity Framework & DbContext Approach

We have discussed optimization with Entity Framework Entity Context or Entity Object approach as the application was built with Visual Studio 2010. But with Visual Studio 2012 default EDMX templates generate classes based on DbContext approach so here we will see how to optimize entity model serialization with DbContext.

Serializing DbContext Entity Model Class

When we try to serialize DbContext model class into JSON it will throw an exception as displayed in below image.

For clear separation of topic, we are not discussing here why this exception thrown with DbContext while it was working fine with Entity Context approach but for now it is preventing us to serialize DbContext model class into JSON. So what’s solution for it? Custom JSON Converter yes again custom JSON converter can be used to resolve this exception. So below is the code of Custom JSON Converter which will allow us to serialize DbContext model class into JSON.

public class EFNavigationPropertyConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        bool isValid = false;
            
        if (objectType.IsGenericType && 
            objectType.GetGenericTypeDefinition().FullName.
            Contains("System.Collections.Generic.HashSet"))
        {
            isValid = true;
        }
 
        return isValid;
    }
 
    // other code removed for clarity
}

DbContext model populates navigation property with System.Collections.Generic.HashSet collection. So we are serializing NULL for it and below is the image which shows response with above custom JSON Converter.

In above image we can see that how custom JSON converter enable us to serialize DbContext model and omitting serialization of Navigation Property for child table.

Separate View Model & Mapper Library

Yes we can create separate view model and can get rid from all above custom JSON converter and etc. but what are the things we need to take care in such cases. Below is the list of prime points.

  • Whenever any new property is added in entity model we need to sync our view model with it.
  • Entity Model to View Model Conversion: if we are manually handling this conversion then we need to alter code at each place and if we are using mapper library than it might requires to change configuration of Object Mapping. This depends on newly added property sometime we even do not require to alter Object Mapping.
  • Processing Overhead: if we are creating separate type for View Model then first it will populate custom View Model and then after it will serialize it into JSON. While in case of Entity Model as a View Model, it will take care of omitting Navigation Property on the fly at a time of serialization so there is less processing overhead in Entity Model as a View Model.

Conclusion

As noted in starting, this post is not to discuss or justify whether Entity Model should be used as View Model or not but here we have tried to discuss small but useful tip which can lead performance improvements while JSON serializing in ASP.NET MVC application with Entity Framework. Hope this would be helpful.

You can follow me on twitter for latest link and update on ASP.NET & MVC.

comments powered by Disqus

Featured Content

Resources & Tools

About Nandip Makwana

Nandip Makwana is passionate about digital world and web. He completed his Masters in Computer Application in June 2011. Currently he is working as a Software Engineer. He has shown great promise and command over ASP.NET and technologies surrounding it during his academic years and professorial life...continue reading