Friday, July 10, 2020

Purse dynamic JSON with C#

First, let me explain what is we are trying to do in this post. Recently have a problem needed to parse a JSON to a C# object. Few of the fields are fixed whereas few are dynamic in nature. Like in the following JSON-
 
{
  "text": "TestallDay",
  "description": null,
  "recurrenceRule": null,
  "id": 238,
  "recurrenceException": null,
  "allDay": true,
  "startDate": "2020-07-07T05:00:00Z",
  "endDate": "2020-07-08T05:00:00Z",
  "resourceTypeId_52": [
    134
  ],
  "resourceTypeId_49": [
    118,
    124
  ]
}
There can be multiple such properties with resourceTypeId_* where * is a number and these properties contain an array of integers. Here is how we can solve this in one possible way. Declared a class like below-
 
    public class DataModel
    {
        [JsonProperty("text")]
        public string Text { get; set; }

        [JsonProperty("description")]
        public object Description { get; set; }

        [JsonProperty("recurrenceRule")]
        public object RecurrenceRule { get; set; }
        
        [JsonProperty("Id")]
        public int Id { get; set; }
        
        [JsonProperty("recurrenceException")]
        public object RecurrenceException { get; set; }
        
        [JsonProperty("allDay")]
        public bool AllDay { get; set; }
        
        [JsonProperty("startDate")]
        public DateTime StartDate { get; set; }
        
        [JsonProperty("endDate")]
        public DateTime EndDate { get; set; }
       
        [JsonProperty("ResourceTypeIds")]
        public Dictionary<string, int[]> ResourceTypeIds { get; set; }
    }
Here in the class you can see we have a property of type Dictionary where we need to fill in all such properties. We can use normal JSON conversion (in my case used JsonConvert from Newtonsoft) for other properties and we can use Newtonsoft.Json.Linq.JProperty to loop through all such properties - resourceTypeId_34, resourceTypeId_45 etc and fill in the values in integer dictionary. Here is the code-
 
            string json = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\",\"resourceTypeId_52\":[134],\"resourceTypeId_49\":[118,124]}";
            
            var data = JsonConvert.DeserializeObject<DataModel>(json);
            data.ResourceTypeIds = new Dictionary<string, int[]>();
            JObject item = JObject.Parse(json);

            IEnumerable<JProperty> props = item.Properties().Where(p => p.Name.Contains("resourceTypeId"));
            foreach (var prop in props)
            {
                List<int> arrayItems = new List<int>();
                foreach (var arrItem in prop.Value)
                {
                    arrayItems.Add((int)arrItem);
                }
                data.ResourceTypeIds.Add(prop.Name, arrayItems.ToArray());
            }

The output looks like this screenshot-

 
IEnumerable<JProperty> props = item.Properties().Where(p => p.Name.Contains("resourceTypeId"));
            foreach (var (prop, arrayItems) in from prop in props
                                               let arrayItems = (from arrItem in prop.Value
                                                                 select (int)arrItem).ToList()
                                               select (prop, arrayItems))
            {
                data.ResourceTypeIds.Add(prop.Name, arrayItems.ToArray());
            }
Complete source code can be found here

Saturday, July 4, 2020

jqGrid load data from ASP.NET MVC Core controller

In this post, let's see how to bind jqGrid with data from asp.net core MVC with server-side paging. We are using User details as MVC view model. Here is the ViewModel-

    public class UserViewModel
    {
        public string UserId { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
    }

    public class UserPagingViewModel
    {
        public List<UserViewModel> Users { get; set; }
        public int CurrentPage { get; set; }
        public int ItemCount { get; set; }
        public int TotalPages { get; set; }
    }

Here UserPagingViewModel is used for pagination details for the grid.

Following is the controller and action method-

    public class _2168660_How_to_load_jQgrid_with_Json_data_coming_from_database_in_ASP_NET_COREController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public UserPagingViewModel GetUsers(int page, int rows, string sidx, string sort)
        {
         //todo: use sidx and sort is not used, also read data from database 
            UserPagingViewModel model = new UserPagingViewModel();
            model.ItemCount = 500;
            model.CurrentPage = page;
            model.TotalPages = model.ItemCount / rows;

            var users = new List<UserViewModel<();
            for (int i = 0; i < rows; i++)
            {
                users.Add(GetRandomData.GetRandomDataObject<UserViewModel>());
            }
            model.Users = users;
            return model;
        }
    }

Here, GetRandomDataObject is not included in the source code, what it does is simply creates some rendom data list.

Below is the view part. jQuery reference is missing which you need to include. In my case it is included in the layout page. Here jsonReader is used to convert response to jqGrid desired.

<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" integrity="sha512-aOG0c6nPNzGk+5zjwyJaoRUgCdOrfSDhmMID2u4+OIslr0GjpLKo7Xm0Ao3xmpM4T8AmIouRkqwj1nrdVsLKEQ==" rel="stylesheet"></link>
<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.5/css/ui.jqgrid.min.css" integrity="sha512-xAIWSSbGucVRdutqUD0VLDowcMF/K8W87EbIoa9YUYB4bTyt/zeykyuu9Sjp0TPVdgrgGgBVCBowKv46wY5gDQ==" rel="stylesheet"></link>
<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.5/plugins/css/ui.multiselect.min.css" integrity="sha512-UuhJihFIXhnP4QEzaNXfLmzY9W3xoeTDATm0buV4wb2qJKoikNn568f0zA5QmrX0sp6VZzqE6fffvsTYU34tGA==" rel="stylesheet"></link>

<script crossorigin="anonymous" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script crossorigin="anonymous" integrity="sha512-xt9pysburfYgFvYEtlhPDo8qBEPsupsDvWB8+iwspD+oQTvAdDEpA1aIKcH6zuABU528YitH6jtP0cAe5GrwKA==" src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.15.5/jquery.jqgrid.min.js"></script>

<table id="dataTable"></table>
<div id="pager"></div>

<script>
    jQuery("#dataTable").jqGrid({
   	url:'@Url.Action("GetUsers", "_2168660_How_to_load_jQgrid_with_Json_data_coming_from_database_in_ASP_NET_CORE")',
	datatype: "json",
    mtype: 'POST',
   	colNames:['User id','User name', 'Email', 'Phone'],
   	colModel:[
   		{name:'userId',index:'userId', width:100},
   		{name:'userName',index:'userName', width:200},
   		{name:'email',index:'email', width:80, align:"right"},
   		{name:'phone',index:'phone', width:80, align:"right"}		
   	],
   	rowList:[10,20,30],
   	pager: '#pager',
    width: '700',
    rowNum:10,
   	sortname: 'userId',
    viewrecords: true,
    sortorder: "desc",
    jsonReader: {
        repeatitems: false,
        root: function(obj) { return obj.users; },
        page: function(obj) { return obj.currentPage; },
        total: function(obj) { return obj.totalPages; },
        records: function(obj) { return obj.itemCount; },
        id: "userId"
    },
    caption:"JSON Example"
});
jQuery("#list2").jqGrid('navGrid','#pager',{edit:false,add:false,del:false});
</script>

You can clone the working copy from Github