Search code examples
jsonasp.net-core.net-corerazor-pages

Razor Pages .Net Core passing a multi-layer JSON object with Children, parents and images back from Mathod


I have a Razor Pages .Net Core application where I am making an ajax call back into a method in order to retrieve more records to display on screen:

    public async Task<IActionResult> OnGetTimelineEntries(int pageIndex, int pageSize)
    {
        //System.Threading.Thread.Sleep(4000);

        ApplicationUser currentAppUser = await _userManager.GetUserAsync(User);

        PopulateUsersEntries(currentAppUser);
        GetHookUps(currentAppUser);

        foreach (ApplicationUser appUser in AppUsersList)
        {
            PopulateUsersEntries(appUser);
        }

        // The above code just populates the below Entries list:

        var pagedEntries = Entries
                            .Skip(pageIndex * pageSize)
                            .Take(pageSize);

        return new JsonResult(pagedEntries.Select(a => new
        {
            Comment = a.Comment,
            thumbNailImage = a.Trip.Season.AppUser.ApplicationUserImage.ImageDataThumb,
            IsEstimatedWeight = a.IsEstimatedWeight,
            tripTitle = a.Trip.Title,
            entryImagesCount = a.EntryImages.Count,
            tripSeasonTitle = a.Trip.Season.Title,
            appUserFirstName = a.Trip.Season.AppUser.FirstName,
            appUserLastName = a.Trip.Season.AppUser.LastName,
            entryTime = a.EntryTime.ToShortTimeString() + " - " + a.EntryTime.ToString("dd MMM yyyy"),
            isCatch = a.IsCatch,
            entryId = a.ID,
            imagesCount = a.EntryImages.Count,
            firstEntryImage = a.EntryImages.FirstOrDefault(),
            fishSpeciesDescription = a.FishSpecies.Description,
            fishWeightDescription = a.Weight + " " + a.WeightUnit.Description,
            entryImages = a.EntryImages


        }));

        //return new JsonResult(pagedEntries);
        //return new JsonResult(pagedEntries.Select(a => new { results = a }));

    }

As you can see, it is returning a JSON object where I am having to SELECT the fields I want from the object to pass them back in a 'flat' JSON object. If I try to pass the whole pagedEntries object back through JSON (return new JsonResult(pagedEntries);) I get an error in the AJAX result (with not much info at all to diagnose).

$.ajax({
    url: '?handler=TimelineEntries',
    beforeSend: function (xhr) { xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val()); },
    data: { "pageindex": pageIndex, "pagesize": pageSize },
    type: "GET",
    success: function (data) {
        debugger;

        if (data != null) {
            for (var i = 0; i < data.length; i++) {
                $("#container").append("<h2>" +
                    data[i].comment +
                    "</h2 > "
                );
            }
            pageIndex++;
        }
    },
    beforeSend: function () {
        $("#progress").show();
    },
    complete: function () {
        $("#progress").hide();
    },
    error: function (e) {
        debugger;
        alert("Error while retrieving data!");
    }
});

Is there a better way I am able to pass the object pagedEntries back to the partial view AJAX call with all its child objects in tact so I dont have to flatten the results into a 1D JSON object?


Solution

  • Okay, so when I was able to debug further I found that if I stripped my model back to only include single child objects, it did work fine. The problems I had were:

    1. Parent objects were preventing a success (child objects were fine)
    2. Large images

    For the parents objects I did some research and found I needed to make sure I had the latest Microsoft.AspNetCore.Mvc.NewtonsoftJson package installed:

    enter image description here

    and that it was correctly referenced in Startup.cs (public void ConfigureServices(IServiceCollection services) method:

    services.AddControllersWithViews()
        .AddNewtonsoftJson(options =>
        options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );
    

    Ton ensure I was okay to pass over larger image and video files, this seems to be doing the trick so far (in web.config)

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

    I am now getting back my full model in the ajax: success function including all Child objects, Parent objects and base64 image strings.