3

I'm trying to figure out why my AJAX POST request is showing up as null when it gets to the controller side. I've tried many variations, but below is what I have right now.

Right now I'm only trying to get a Question with Type to go through, so most of the Model is not needed, and can be null.

What's most odd to me is that not only can I see the data is the request info using Chrome's debugging tools, but a very similar method is working (although, the model does not have lists in it. Also, It other areas of the site, I have used that model for submitting, and it works.

Also, it's not just AJAX, I've tried just doing a regular submit, and it does the same thing.

Below I believe is everything of interest. Let me know if something else is needed.

Updates from chat:

The type QuestionType is an enum, and the values 0-2 are valid for it.

I've tried using jQuery, including using the serialize() method shown here. This did nothing.

I've confirmed what is being sent, it is the first one with a normal submit, and the second one when using jQuery.

"QuestionID=-1&Question=Are+you+alive"%"3F&Type=0"


"QuestionID=-1&Question=Are+you+alive%3F&Type=0"

Model

public class QuestionnaireViewModel
{

    [Required]
    public QuestionType Type { get; set; }

    public int QuestionID { get; set; }

    [Required]
    public string Question { get; set; }

    public string RadioOption { get; set; }

    public List<string> Options { get; set; }

    public List<bool> MC_Answers { get; set; }

    public string ShortAnswer { get; set; }
}

HTML

<form action="/Staffing/SaveQuestion" class="form-horizontal" method="post" role="form">
    <input data-val="true" data-val-number="The field QuestionID must be a number." data-val-required="The QuestionID field is required." id="QuestionID" name="QuestionID" type="hidden" value="5">
    <div class="form-group">
        <label for="Question">Question</label>
        <input class="form-control editDisplayText" data-val="true" data-val-required="The Question field is required." id="Question" name="Question" type="text" value="">
        <span class="field-validation-valid text-danger" data-valmsg-for="Question" data-valmsg-replace="true"></span>
    </div>
    <div class="form-group">
        <label class="control-label col-md-2" for="Type">Type</label>
        <div class="col-md-10">
            <select class="form-control questionTypeDD" data-val="true" data-val-required="The Type field is required." id="Type" name="Type">
                <option selected="selected" value="0">SHORT</option>
                <option value="1">RADIO</option>
                <option value="2">CHECKBOX</option>
            </select>
        </div>
        <span class="field-validation-valid text-danger" data-valmsg-for="Type" data-valmsg-replace="true"></span>
    </div>
    <div class="form-group">
        <div class="col-md-12">
            <input type="submit" value="Save Edits" class="btn btn-default pull-right">
        </div>
    </div>
</form>

AJAX

function submitQuestion(event) {
    event.preventDefault();
    var radio, checkbox;

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

            if (xmlhttp.responseText.indexOf("Success") >= 0) {
                restoreEdit();

                var currentJob = document.getElementById('currentJob');
                if (currentJob != null && currentJob != undefined) {
                    clearQuestions();
                    getJobQuestionsById(currentJob.innerHTML);
                    addQuestionEventHandlers();
                }
                else {
                    alert("Question added successfully");
                }
            }
            else {
                alert(xmlhttp.responseText);
            }
        }
    }

    var form = event.currentTarget;
    var formData = new FormData(form);
    xmlhttp.open("POST", form.action, false);
    xmlhttp.send(formData);
}

HTTP Request

curl "http://localhost:49345/Staffing/SaveQuestion" -H "Origin: http://localhost:49345" -H "Accept-Encoding: gzip, deflate" -H "Accept-Language: en-US,en;q=0.8" -H "User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryU4mNITZXngk0WZ8C" -H "Accept: /" -H "Referer: http://localhost:49345/Staffing/Dashboard" -H "Connection: keep-alive" -H "DNT: 1" --data-binary "------WebKitFormBoundaryU4mNITZXngk0WZ8C"^ "Content-Disposition: form-data; name=""QuestionID"""^

"-1"^ "------WebKitFormBoundaryU4mNITZXngk0WZ8C"^ "Content-Disposition: form-data; name=""Question"""^

"Are you alive?"^ "------WebKitFormBoundaryU4mNITZXngk0WZ8C"^ "Content-Disposition: form-data; name=""Type"""^

"0"^ "------WebKitFormBoundaryU4mNITZXngk0WZ8C--"^ "" --compressed

David
  • 4,744
  • 5
  • 33
  • 64
  • who is calling submitQuestion function. – Karthik M R Apr 23 '16 at 16:31
  • A different page than itself. Same page that calls the other similar one. – David Apr 23 '16 at 16:44
  • ok. what is the request body which is being passed captured from developer tools. – Karthik M R Apr 23 '16 at 16:54
  • Since your viewmodel class has other complex types, the form data cannot be converted back to the complex types.in this case, QuestionID and Question properties are populated but not Type which is of type QuestionType. So best way is to send the corresponding json data from client. then modelbinder populates even for the complex types. – Karthik M R Apr 23 '16 at 17:13
  • Request body is already in the post, guessing you saw that. So, is the reason it doesn't work is because it's going to another page, or because it has the complex types? And so, I just need to, instead of sending a URL encoded form, send JSON and it will work? If you had any tutorials on that, that would be helpful. – David Apr 23 '16 at 19:42
  • Also, why would it work on other pages, but not this one? – David Apr 23 '16 at 22:15
  • Can you post here the QuestionType class. Basically what you can do is for QuestionType dropdownlist, you can give the name as name="Type.QuestionTypeProperty". Then this type will be populated with value attribute. – Karthik M R Apr 24 '16 at 03:26
  • @KarthikMR QuestionType is just an enum. – David Apr 24 '16 at 03:43
  • If its enum type, it should populate the model. what is the POST data which is being passed? is it like QuestionId=5&Question=aaa&Type={either1or2or3} – Karthik M R Apr 24 '16 at 03:59
  • I have the HTTP request in my original question. If you look, you'll see that QuestionID = -1; Question = "Are you alive?"; and Type = 0. The rest of the model is left unpassed. – David Apr 24 '16 at 04:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110043/discussion-between-karthik-m-r-and-david). – Karthik M R Apr 24 '16 at 05:05
  • @KarthikMR, see answer. Ahhh, it's so stupid. – David Apr 24 '16 at 06:40
  • Oopps... Totally unexpected behavior. – Karthik M R Apr 24 '16 at 10:54

1 Answers1

1

I finally found the solution thank to this post! Model is null when form submitted

My controller was this:

public ActionResult SaveQuestion(QuestionnaireViewModel question)

Which apparently was an issue because of this (even with the different casing):

public string Question { get; set; }

The solution was this:

public ActionResult SaveQuestion(QuestionnaireViewModel postQuestion)

Basically, the name of the object being accepted cannot be the same name as one of the properties, or apparently MVC freaks out.

Community
  • 1
  • 1
David
  • 4,744
  • 5
  • 33
  • 64