5

I am having a strange problem with ASP.NET MVC and sending an AJAX post. I have an anchor tag on the page with id 'lnkGetExpirDates'. When the user clicks it I am trying to simply send this hardcoded data to my controller so it can use it as params and return a result back to the page.

However, in the controller the params are always null/default values. Please see my code below and let me know if I am making a silly mistake or something.

Here is my AJAX post:

$("#lnkGetExpirDates").click(function () {
    e.preventDefault();

    var data = {
        StartDate: "1/19/2016",
        EndDate: "4/19/2016",
        ProductType: "New",
        Count: 1
    };


    $.ajax({
        url: '/Products/GetExpirationDates',
        type: 'POST',
        data: JSON.stringify(data),
        contentType: 'application/json; charset=utf-8',
        dataType: 'html',
        success: function (data) {
            $('#ExpirationDates').val(data);
        }
    });

});

Here is my controller's action method:

// POST: Product/GetExpirationDates
[HttpPost]
//[ValidateAntiForgeryToken]
public IActionResult GetExpirationDates(GetExpirationDatesViewModel vm)
{
    // TODO: Get expiration dates and return them in the response

    return View();
}

Here is the GetExpirationDatesViewModel:

public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string ProductType { get; set; }
public int Count { get; set; }

Please note that I have even tried this without using a model at all and simply just adding parameters to the Action Method such as startDate, endDate, productType, and Count and still everything comes in as null.

Blake Rivell
  • 13,105
  • 31
  • 115
  • 231

1 Answers1

12

When you specify the content type value as application/json, the ajax request made to server will send your js object as the Request Payload, in the body of the request (in json format). So in your action method you should use the [FromBody] attribute.

public IActionResult GetExpirationDates([FromBody] GetExpirationDatesViewModel vm)
{
   return View();
}

You should do this when you want to send a complex js object with properties which is again another model/type

But the data you are sending is a flat view model. So you do not really need to json stringify the js object. Also you may remove the content type property as well as you are not going to send a stringified version of a complex js object.

This should work fine.

$.ajax({
    url: '/Products/GetExpirationDates',
    type: 'POST',
    data: data,      
    dataType: 'html',
    success: function (data) {
        console(data);
    }
});

The above code will send the js object as key value pairs (normal form data) and the model binder will be able to map the form data to your view model object in the server. Take a look at this post for more detailed explanation.

Also i recommend you to use the Url.Action helper method to generate the proper relative url to the action method(s).

url: '@Url.Action("GetExpirationDates","Products")',

The above should work if your js code is inside a razor view. If your code is inside an external js file, Use the solution described in this post.

Community
  • 1
  • 1
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • I really appreciate this. It worked perfectly. Can you explain to me when it would be a good idea to use JSON.stringify? I am assuming when posting an entire form as JSON? – Blake Rivell Feb 16 '16 at 20:30
  • And one other small question. Lets say I need to ultimately return a list of dates back to the webpage. What would my return in my action method look like? Additionally it is a bit strange how when I send a date like Fri Feb 26 2016 00:00:00 GMT-0500 (Eastern Standard Time) as a param it doesn't take it. I guess I can only convert it to a short date then send... – Blake Rivell Feb 16 '16 at 20:37
  • 2
    Take the updated answer. If you want to send a list of dates, you can return that as JSON data using `Json()` method. See a sample here http://stackoverflow.com/questions/10608198/asp-net-mvc3-returning-success-jsonresult/10608250#10608250 – Shyju Feb 16 '16 at 20:46
  • Thank so so much for everything! – Blake Rivell Feb 16 '16 at 20:47