Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery Post to ASP.NET API Controller

I have a form that is generated via jquery:

 $.get("/api/get/getListItems", function (data) {
                var table = "";
                table += "<table>";
                $.each(data, function (y, z) {
                    console.log(z);
                    table += '<tr>';
                    $.each(this, function (k, v) {
                        table += '<td><input type="text" name="' + k + '" id="' + k + '" value="' + v + '" /></td>';
                    });
                    table += '<td><input type="checkbox" name="selected" id="selected" /></td>';

                    table += '</tr>';
                });
                table += '<tr><td><input type="submit" id="submit" name="submit" value="Save To Database" /></td></tr>';
                table += '</table>';
                $('#form').html(table);
            });

and it generates this HTML (10 rows of input fields, 7 columns and 1 checkbox): http://jsfiddle.net/8zpr2fkL/1/

and I am submitting the form when the submit button is clicked:

$("#form").submit(function (event) {
        $.post("/api/update/", $("#form").serialize(), alert('success'));
    });

Now I am passing the data to my ASP.NET API Controller:

[HttpPost]
        public dynamic Post([FromBody]CellModel cells)
        {
                UpdateClass jobs = new UpdateClass();
                return jobs;
        }

and here is my CellModel class:

public class CellModel
    {
        public uint scheduleTaskID { get; set; }
        public string task { get; set; }
        public string baselineDate { get; set; }
        public string scheduledDate { get; set; }
        public string actualDate { get; set; }
        public string finishedDate { get; set; }
        public bool selected { get; set; }

        public override string ToString()
        {
            return scheduleTaskID.ToString();
        }
    }

My Problem is when I hit submit to submit the data and put a breakpoint on the controller method, cells count is 0, is there something I am missing here? I am trying to pass all the data in the input text to controller. Nothing is getting passed to my controller. What am I doing wrong?

This is data im trying to pass via jquery $('#form').serialize():

scheduleTaskID=194&task=Permit&baselineDate=6%2F23%2F2005+8%3A00%3A00+AM&scheduledDate=6%2F23%2F2005+8%3A00%3A00+AM&actualDate=6%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=195&task=Office+Files&baselineDate=7%2F13%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F13%2F2005+8%3A00%3A00+AM&actualDate=7%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=196&task=Foundation&baselineDate=7%2F27%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F27%2F2005+8%3A00%3A00+AM&actualDate=8%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=197&task=Framing&baselineDate=8%2F5%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F5%2F2005+8%3A00%3A00+AM&actualDate=8%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=198&task=Finishes+Exterior&baselineDate=8%2F26%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F26%2F2005+8%3A00%3A00+AM&actualDate=9%2F14%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=199&task=Drywall&baselineDate=9%2F2%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F2%2F2005+8%3A00%3A00+AM&actualDate=9%2F16%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=200&task=Flooring&baselineDate=9%2F1%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F1%2F2005+8%3A00%3A00+AM&actualDate=9%2F20%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=201&task=General+Finish&baselineDate=9%2F12%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F12%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=202&task=Final+PDI&baselineDate=10%2F11%2F2005+8%3A00%3A00+AM&scheduledDate=10%2F11%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=203&task=Permit&baselineDate=4%2F6%2F2005+8%3A00%3A00+AM&scheduledDate=4%2F6%2F2005+8%3A00%3A00+AM&actualDate=4%2F6%2F2005+8%3A00%3A00+AM&finishedDate=

UPDATE

I have changed:

$("#form").submit(function (event) {
            $.post("/api/update/", $("#form").serialize(), alert('success'));
        });

to

$("#form").submit(function (event) {
        var array = [];
        $('#form > table > tbody  > tr').each(function (elem) {
            var item = {};
            item.scheduleTaskID = $(this).find("td > #scheduleTaskID").val();
            item.task = $(this).find("td > #task").val();
            item.baselineDate = $(this).find("td > #baselineDate").val();
            item.scheduledDate = $(this).find("td > #scheduledDate").val();
            item.actualDate = $(this).find("td > #actualDate").val();
            item.finishedDate = $(this).find("td > #finishedDate").val();
            item.selected = $(this).find("td > #selected").val();
            array.push(item);
        });
        console.log(JSON.stringify(array));
        $.post("/api/update/", JSON.stringify(array), alert('success'), 'json');
    });

in my console log my data looks like this:

[{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"195","task":"Office Files","baselineDate":"7/13/2005 8:00:00 AM","scheduledDate":"7/13/2005 8:00:00 AM","actualDate":"7/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"196","task":"Foundation","baselineDate":"7/27/2005 8:00:00 AM","scheduledDate":"7/27/2005 8:00:00 AM","actualDate":"8/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"197","task":"Framing","baselineDate":"8/5/2005 8:00:00 AM","scheduledDate":"8/5/2005 8:00:00 AM","actualDate":"8/23/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"198","task":"Finishes Exterior","baselineDate":"8/26/2005 8:00:00 AM","scheduledDate":"8/26/2005 8:00:00 AM","actualDate":"9/14/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"199","task":"Drywall","baselineDate":"9/2/2005 8:00:00 AM","scheduledDate":"9/2/2005 8:00:00 AM","actualDate":"9/16/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"200","task":"Flooring","baselineDate":"9/1/2005 8:00:00 AM","scheduledDate":"9/1/2005 8:00:00 AM","actualDate":"9/20/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"201","task":"General Finish","baselineDate":"9/12/2005 8:00:00 AM","scheduledDate":"9/12/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"202","task":"Final PDI","baselineDate":"10/11/2005 8:00:00 AM","scheduledDate":"10/11/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{}]

and in my ASP.NET API Controller, I changed my method to this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class UpdateController : ApiController
    {
        [HttpPost]
        public dynamic Post(List<CellModel> cells)
        {
                UpdateClass jobs = new UpdateClass();
                //jobs.PostScheduledTasks(cells);
                return cells;
        }

    }
}

I put a breakpoint at the start of the method Post and when it hits the breakpoint, it says cells Count = 0..I see network call, only if i put a return false after my post call and the response is empty [] Why is the data not passing to my controller, is it because the form is being generated by jquery?

UPDATE

Still no solution, I looked at my network call this AM and the Status Code is 301:

enter image description here

like image 367
user979331 Avatar asked Oct 22 '14 13:10

user979331


2 Answers

Don't use $.post use ajax post and set the content type to "application/json; charset=utf-8"

var data = JSON.stringify(array);
$.ajax({
  url:"/api/update/",
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(data){
    console.log(data);
  }
});

the problem is that you need to say to the webserver you are sending json and is not possible with $.post

This is really normal, and I have been struggling with this too (and sometimes I still forget), here you can see that you have to use $.ajax

Jquery - How to make $.post() use contentType=application/json?

like image 137
dariogriffo Avatar answered Nov 11 '22 16:11

dariogriffo


While you got an alternative approach by @dariogriffo, i want to give you a full solution using your initial approach with $.post.

Your initial approach with form serialization was correct, so the following code is correct:

$("#form").submit(function (event) {
   $.post("/api/update/", $("#form").serialize(), alert('success'));
});

However, this wasn't working because your dynamic form is not following the naming conventions for input fields expected by the ASP.NET MVC Default model binder, and as a consequence your serialized form was not something the default model binder was capable of binding to your cells model. That is why you were not getting any cells in the controller when doing a POST.

To clarify what that means, ASP.NET expects each input field that corresponds to a model property to have the following name format if you are posting to a regular MVC 5 Controller:

actionattributename[index].propertyname

If you are posting to a Web API 2 controller it should be:

[index].propertyname

Since your action attribute is named cells and it has a property scheduledTaskID, and you are posting to a WebAPI controller one of your inputs would look like:

<input type="text" name="[0].scheduleTaskID" id="scheduleTaskID" value="194">

There are a couple more rules involved in structuring a form to make it bindable. You can find a nice blog post about it here:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

If you followed that form convention you would be able to Post your serialized form to your controller expecting a List<CellModel> cells without having to use the JSON approach, which is much more expensive as suggested in the other answers.

Below is a fiddle with an example form structured correctly by Web API 2 default binder rules:

http://jsfiddle.net/8zpr2fkL/12/

You can try to $.post this form using $.post to your web api controller and it should work like a charm!

like image 23
Faris Zacina Avatar answered Nov 11 '22 18:11

Faris Zacina