2

I'm revisiting a problem I had early on with a page that contains quite a few input and select controls in a form. I prefer that my Controller Action uses the View Model to determine the input values, but the model's members are always empty when submitted. Here is my undesirable WORKING code, briefly:

VIEW MODEL:

public class MyViewModel
{
    [Display(Name = "Project Name")]
    public string ProjectName { get; set; }

    [Display(Name = "Project Country")]
    public string ProjectCountry { get; set; }
    public IEnumerable<SelectListItem> Countries { get; set; }
}

RAZOR VIEW:

@model My_Web_App.Models.MyViewModel

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myform" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        @Html.LabelFor(model => model.ProjectName)
        <div class="col-md-9">
            @Html.EditorFor(model => model.ProjectName)
        </div>
    </div>

    <!-- Project Country -->
    <div class="form-group">
        @Html.LabelFor(model => model.ProjectCountry)
        <div class="col-md-4">
            @Html.DropDownListFor(
                x => x.ProjectCountry,
                new SelectList(Model.Countries, "Value", "Text"))
        </div>
    </div>

    <table id="mytable">
    <thead>
        <tr>
            <th>Data1</th>
            <th>Data2</th>
            <th>Data3</th>
        </tr>
    </thead>

    <tbody></tbody>
    </table>

    <button id="btnSubmit" type="submit">Submit</button>
}

<script type="text/javascript">
    $('#btnSubmit').click(function (event) {
        event.preventDefault();

        oTable = $('#mytable').dataTable({
            "ajax": {
                "url": "/MyController/MyJsonResult/",
                "type": "POST",
                "data": {
                    ProjectName: $('#ProjectName').val(),
                    ProjectCountry: $('#ProjectCountry').val()         
                }
            }
        });

    return false;
    });
</script>

CONTROLLER:

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult MyJsonResult()
{
    string projectName = Request["ProjectName"];
    string projectCountry = Request["ProjectCountry"];

    ... DO SOMETHING ...

    return Json(new { data = dosomethingresult }, JsonRequestBehavior.AllowGet);
}

The above code works in that I can get the View's form variables and use them to determine the results to return. Obviously I've left out a lot of code, a lot of form variables, and a lot of controller logic. I don't want to convert strings to integers, worry about whether a POST var is empty or null, etc. There are so many form variables I would like MVC to take care of this for me. For example:

PREFERRED CONTROLLER ACTION:

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult MyJsonResult(MyViewModel model)
{
    string projectName = model.ProjectName;
    string projectCountry = model.ProjectCountry;

    ... DO SOMETHING ...

    return Json(new { data = dosomethingresult }, JsonRequestBehavior.AllowGet);
}

The problem with the preferred controller action above is that the contents of model are always null when using DataTables Ajax.

model is initialized with valid data if I make the Ajax call outside of the DataTables initialization. :

$('#btnSubmit').click(function (event) {
    event.preventDefault();

    $.ajax({
        url: "/MyController/MyJsonResult/",
        type: "POST",
        dataType: "json",
        data: $('#myform').serialize()
    });

    return false;
}

The data setting just above correctly serializes all of the form fields and MVC successfully creates the View Model object for me to use in the Controller Action. Unfortunately, "data": $('#myform').serialize() in the DataTables Ajax does not work. The model is uninitialized (nulls and zeros) when the Controller Action is called.

How can I pass my entire form to the Controller Action using DataTables Ajax so that my View Model object contains correct data from the View's form?

I have been searching for a solution for a long time. Way too long. :S

rwkiii
  • 5,716
  • 18
  • 65
  • 114
  • Try `var temp = $('form').serializeArray();var data = {};$.map(temp, function (n, i) {data[n['name']] = n['value'];});` then in the ajax call `... data: data, traditional: true, ...` –  Oct 03 '14 at 06:13
  • possible duplicate of [Serialize form data to json](http://stackoverflow.com/questions/11338774/serialize-form-data-to-json) – freshbm Oct 03 '14 at 06:39
  • @Stephen Muecke, your suggestion partially works, but not completely. For some reason checkbox values are null and select values contain `count=0`. – rwkiii Oct 03 '14 at 14:26
  • 1
    @freshbm, I understand that your referenced post touches on this problem, but I don't see anyone mentioning DataTables. Its Ajax seems to be different than straight jQuery Ajax. On top of this, there is no accepted answer and there seems to be at least some debate left in that post as to what works and what doesn't. It contains some good info though. I just don't see how my post is a duplicate of the one you reference. – rwkiii Oct 03 '14 at 14:30

1 Answers1

0

Try this in your Razor view:

@using (Html.BeginForm("MyJsonResult", "MyController", FormMethod.Post, new { id = "myform" }))
Mike Manard
  • 1,020
  • 9
  • 13