0

Working in ASP.NET Core where I'm trying to POST a List of Items through Ajax. Ideally, I would like to pass the entire ReportViewModel but I haven't been able to match the signature correctly (since passing a DateTime or a List isn't that easy).

My question

  1. How to POST a List<Object> from the view with Ajax to the controller?
  2. OR How to POST a Model from the view with Ajax to the controller?

I currently have the following code:

Models

public class ReportViewModel {
    public int ReportType { get; set; };
    public DateTime DateFrom { get; set; };
    public DateTime DateTo { get; set; };
    public List<Item> ItemList{ get; set; };
}

public class Item {
    // Properties are simple types
}

View (ReportView)

@model Namespace.ViewModels.ReportViewModel
@inject Namespace.Resource Resources
<!-- HTML code -->
<form>
<button class="ui button" type="submit" onclick="return createPDF();">@Resources.Save</button>
</form>

<script>
  function createPDF() {
    alertify.set('notifier', 'position', 'bottom-left');

    $.ajax({
      type: "POST",
      url: "CreatePDF",
      data: JSON.stringify({
        reportType: @Model.ReportType,
        ticksDateFrom: @Model.DateFrom.Ticks,
        ticksDateTo: @Model.DateTo.Ticks
        @* TODO: Add the List<Items> itemList (from @Model.ItemList)*@
      }),
      contentType: 'application/json',
      // Code for success and error
    });

    return false;
  };
</script>

Controller (ReportController)

[HttpPost]
public JsonResult CreatePDF([FromBody] dynamic data) {
    // Lots of code
    return Json(new { isError = false });
}

/* When passing the entire model
* [HttpPost]
* public JsonResult CreatePDF([FromBody] ReportViewModel model) {
*     // Lots of code
*     return Json(new { isError = false });
* }
*/

I tried passing the model as seen below but that leaves me with the parameter in the controller being null or as a new "empty" object, depending if I use [FromBody] or not.

$.ajax({
  type: "POST",
  url: "CreatePDF",
  data: @Html.Raw(Json.Serialize(Model)),
  contentType: 'application/json',
  // Code for success and error
});
5
  • Why in the world are you trying to post back the whole model. Just post back the ID and get the model again based on the ID (and with your current code, it would need to be data: JSON.stringify( { model: @Html.Raw({ Json.Serialize(Model)) }), where the parameter is ReportViewModel model) Commented Jul 27, 2018 at 10:54
  • @StephenMuecke The model itself isn't actually saved and is populated by the propeties chosen within the form of the view Commented Jul 27, 2018 at 11:10
  • Your code is serializing a model that you sent in the GET method :) (it is just degrading performance to send it all to the view and send it all back again unchanged) Commented Jul 27, 2018 at 11:12
  • @StephenMuecke To clarify the flow a bit more: First we send the model from the controller to the view with GET, modify the model by choosing properties and then send it to a POST. However the POST which will receive the model is not the same POST as the one who would receive the form. I need to pass it because the logic is split up. Commented Jul 27, 2018 at 11:18
  • Your sending back the original model (that is what Json.Serialize(Model) does), not anything that has been modified :) Commented Jul 27, 2018 at 11:21

2 Answers 2

1

You can use the BeginForm in your view that posts to a controller:

@model Namespace.ViewModels.ReportViewModel
@inject Namespace.Resource Resources

@using (Html.BeginForm("CreatePDF", "[PDFControllerName]", FormMethod.Post, new { @id = "pdfCreatorForm" }))
{
    <!-- Send parameters to a controller like this (invisibly) -->
    @Html.HiddenFor(m => m.ReportType)
    @Html.HiddenFor(m => m.DateFrom.Ticks)
    @Html.HiddenFor(m => m.DateTo.Ticks)
    @Html.HiddenFor(m => m.ItemList) <!-- Send the List<Items> -->

    <button type="submit" class="ui button" onclick="alertify.set('notifier', 'position', 'bottom-left')">@Resources.Save</button>
}

And then you don't need the JavaScript any more, another thing to keep in mind is to keep as much functionality on your server side as you can.

If you POST the form to a controller, you can access the view's parameters etc like this:

public JsonResult CreatePDF(ReportViewModel formData)
{
    int reportType = formData.ReportType;
    DateTime ticksDateFrom = formData.DateFrom.Ticks;
    DateTime ticksDateTo = formData.DateTo.Ticks;
    List<Items> itemList = formData.ItemList;

    // Lots of code
}

And, you actually doesn't need to specify that it's taking in a HttpPost :)

Sign up to request clarification or add additional context in comments.

8 Comments

I appreciate this answer and see this working out for others fairly well. Yet, I can't use this solution in my case because I actually have multiple buttons in my form and multiple methods that could be called (which I didn't add in the question so you couldn't have known). +1 for the good answer - EDIT: Actually I'm not sure if you can use this multiple times within a form, but I'm thinking that you just might. Can it?
Ah, alright, so the idea with ajax is being able to send multiple viewdata/json objects to a controller from a single view x amount of times?... Hmmm...
Well, i'll do it here instead: 1. In your $.ajax, you've set your data to reportModel (variable reference), is this intentional? Because then you are initalizing it somewhere above?
2. That // Lots of code, what does it do? how do you use model? That may have an impact on your return.
1. Thank you for pointing that out, I forgot a crucial part of the code and have now edited the answer. 2. As the method name suggests, I create a PDF and save it to the system. I might as well make a void method here but I want to notify the user and use isError to do that
|
0

I don't know what exactly I changed to make it work but the following compiles correctly. Could be the processData: true and cache: false properties?

Controller

[HttpPost]
public JsonResult CreatePDF([FromBody] ReportViewModel model)
{
    // Lots of code
    return Json(new { isError = false });
}

View (JS only)

$.ajax({
  type: "POST",
  url: "CreatePDF",
  data: JSON.stringify(@Html.Raw(Json.Serialize(Model))),
  contentType: 'application/json; charset=utf-8',
  processData: true,
  cache: false,
  // Code for success and error
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.