0

I am trying to pass a model to the controller using an ajax post, but every time I do so, the model is null and I lose all the data I am trying to persist.

The ajax call:

$('#next').click(function (e) {
    e.preventDefault();
    var url = '@Url.Action("Manage")'
    var _model = JSON.stringify(@Html.Raw(Json.Encode(Model)));
    var _page = @(Model.pager.CurrentPage + 1);

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: url,
        data: JSON.stringify({ 'model': _model, 'page': _page }),
        success: function(result) {
            console.log(result);
        }
    });
});

When I look at the serialized object, it looks like a correctly formatted JSON object with no errors thrown in the developer console.

The link that is triggering this jQuery call is just a basic action link:

@Html.ActionLink(">", "Manage", "Announcements", null, new { id = "next" })

My model is a little more complicated...

public class ManageViewModel : IEnumerable<EditViewModel>
{
    [Display(Name="Start Date")]
    [DataType(DataType.DateTime)]
    public DateTime? StartDate { get; set; }

    [Display(Name="End Date")]
    [DataType(DataType.DateTime)]
    public DateTime? EndDate { get; set; }

    public string SearchString { get; set; }

    public Pager pager { get; set; }

    public List<EditViewModel> Data { get; set; }
    public List<CategoryViewModel> Categories { get; set; }

    public ManageViewModel()
    {
        Data = new List<EditViewModel>();
        Categories = new List<CategoryViewModel>();
    }

    public IEnumerator<EditViewModel> GetEnumerator()
    {
        return Data.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return Data.GetEnumerator();
    }
}

public class Pager
{
    public int TotalItems { get; private set; }
    public int CurrentPage { get; private set; }
    public int PageSize { get; private set; }
    public int TotalPages { get; private set; }
    public int StartPage { get; private set; }
    public int EndPage { get; private set; }

    public Pager(int totalItems, int? page, int pageSize = 10)
    {
        int totalPages = (int)Math.Ceiling((decimal)totalItems / (decimal)pageSize);
        int currentPage = page ?? 1;
        int startPage = currentPage - 5;
        int endPage = currentPage + 4;

        if(startPage <= 0)
        {
            endPage -= (startPage - 1);
            startPage = 1;
        }

        if(endPage > totalPages)
        {
            endPage = totalPages;
            if(endPage > 10)
            {
                startPage = endPage - 9;
            }
        }
        TotalItems = totalItems;
        TotalPages = totalPages;
        CurrentPage = currentPage;
        PageSize = pageSize;
        EndPage = endPage;
        StartPage = startPage;
    }
}

I can't convert the links in to a form because that breaks the pagination. Or maybe I'm just not understanding the full picture here.

Here is the section of the View where the pagination is occurring

if (Model.pager.EndPage > 1)
{
    <div style="color:#337AB7; padding-bottom: 0px;">Page @Model.pager.CurrentPage of @Model.pager.TotalPages</div>
    <ul class="pagination">
        @if (Model.pager.CurrentPage > 1)
        {
            <li>
                @Html.ActionLink("<<", "Manage", new { model = Model, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
            </li>
            <li>
                @Html.ActionLink("<", "Manage", new { model = Model, page = Model.pager.CurrentPage - 1, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
            </li>
        }
        @for (var _page = Model.pager.StartPage; _page < Model.pager.EndPage + 1; _page++)
        {
            <li class="@(_page == Model.pager.CurrentPage ? "active" : "")">
                @Html.ActionLink(_page.ToString(), "Manage", new { model = Model, page = _page, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
            </li>
        }
        @if (Model.pager.CurrentPage < Model.pager.TotalPages)
        {
            <li> 
                @Html.ActionLink(">", "Manage", "Announcements", null, new { id = "next" })
            </li>
            <li>
                @Html.ActionLink(">>", "Manage", new { model = Model, page = Model.pager.TotalPages, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
            </li>
        }
    </ul>
}

The action links attempting to pass the model, obviously don't work but I left them because I am focusing on getting one to work, the one listed previously, before getting all the others configured.

I have looked at the following SO posts and have had no luck with them:
Post an MVC model with AJAX?
Model properties null on Ajax post from list box change event
How to send a model in jQuery $.ajax() post request to MVC controller method
Pass Model To Controller using Jquery/Ajax
How to pass model in ajax post request?

Any ideas on how I might be able to do this? I need the model data to persist for searching/filtering which is done through a form. Thank you in advance for taking a look and giving your insights!

Community
  • 1
  • 1
boost
  • 3
  • 3
  • Why are you sending the Model back (as it is) ? Just the send the unique id from which the model object can be rebuilt in your action method. – Shyju Sep 02 '16 at 15:47
  • There is no ID for the model to reference for this. I'm not trying to get an specific item, I'm trying to persist the data from the model that contains the search criteria for navigating between different pages. – boost Sep 02 '16 at 15:54
  • Did you inspect the "_model" variable and the request from your browser? – Ricardo Pontual Sep 02 '16 at 16:20
  • I did. The _model variable is a valid JSON object, and I get a 200 response from the server. The issue is that the model is null in the controller. I see it being serialized correctly, here is a snippet of the _model `JSON.stringify([{"WATypeName":"Some Value","Categories":[{"ID":6,"Name":" ...` That's what it looks like in Fiddler. I have no errors in the developer console, and the request returns fine. – boost Sep 02 '16 at 16:27
  • I also validated the JSON object using JSONLint.com, and it's a completely valid object. – boost Sep 02 '16 at 16:29
  • Does it really have `JSON.stringify(` in Fiddler? Because that could be the problem... – Heretic Monkey Sep 02 '16 at 17:33
  • It does have that in fiddler. If I remove `JSON.stringify` I receive an `undeclared primitive: model` error, or an error regarding "&" symbol if it's not converted to raw html. – boost Sep 02 '16 at 17:37
  • But it's not in the request, it just displays in the TextView of fiddler. – boost Sep 02 '16 at 17:38

1 Answers1

0

You need to include a parameterless constructor for your models. From the screenshot you have sent it seems there isn't a parameterless constructor for public Pager model.

Asaad
  • 141
  • 1
  • 5