I've been wracking my brain and the various SO posts on the same topic (see JQuery Ajax and Posting multiple complex objects to asp.net MVC Controller, Passing multiple objects to my controller, etc) but I'm having trouble getting multiple objects to post from an Ajax call to my controller (.NET Core). I believe I have set up my code like this tutorial has (http://www.dotnetcurry.com/aspnet-mvc/1253/multiple-model-objects-input-controller-action-methods) and have also used suggestions from here: http://andrewlock.net/model-binding-json-posts-in-asp-net-core/ to no avail.
The issue: I can only get the first, but not the second, object to bind.
Controller method:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Apply(ApplicationInfoViewModel info, SRAgreementViewModel agreement)
{
if(ModelState.IsValid){
//do stuff. ModelState.IsValid returns false here.
}
}
Here's my JS:
$(function () {
$("#ApplyBAOForm").submit(function (e) {
var jsonObj = $('#ApplyForm').serialize();
var srFormJsonObj = $('#SRForm').serialize();
$.ajax({
url: "ApplyBao/Apply",
datatype: "json",
contentType: "application/json; charset=utf-8",
data: { info: jsonObj, agreement: srFormJsonObj },
type: "POST"
}).done(function (result) {
console.log("Apply success: " + result);
if (result.type === "success") {
//hooray
}
else {
//boo
}
});
});
});
So this is a bit of an odd situation: there's actually data from two separate forms here. The SRform data is validated prior to submitting the ApplyForm (it is in a modal), but is only actually submitted for persistence with the ApplyForm. The resulting serialized objects from both forms appears to be correct and similar (jsonObj and srFormObj).
When I hit the ModelState.IsValid statement, it returns false because the SRAgreement object is essentially null (with default values). However, the ApplicationInfoViewModel object correctly shows data from the form.
Other things I've tried:
- combining the two objects into one view model (both child objects wound up being null?)
- Adding the SRAgreement object as a child of the ApplicationInfo object; the SRAgreement object was null.
- adding [FromBody] as described by the blog postfrom Andrew Lock, this jsut resulted in an HTTP 415 unsupported media type response
There's likely a better way to do this, but I would think that what I'm attempting to do should be doable.
Thanks!
EDIT 2:
It appears that I can't even bind one JSON object. I've got to be missing something simple. I've pared it down to just submitting one of the two objects as JSON as such:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Apply([FromBody] ApplicationInfoViewModel info)
{
if (ModelState.IsValid)
{
// do stuff
}
}
JS:
$("#ApplyBAOForm").submit(function (e) {
e.preventDefault();
var jsonObj = ConvertFormToJSON($("#ApplyBAOForm"));
var srFormJsonObj = ConvertFormToJSON($("#SRForm"));
var obj2 = JSON.stringify({ info: jsonObj });
$.ajax({
url: "ApplyBao/Apply",
datatype: "json",
contentType: "application/json; charset=utf-8",
data: obj2,
//data: JSON.stringify(jsonObj),
type: "POST"
}).done(function (result) {
console.log("Apply success: " + result);
}
else {
//show some error message or something
}
});
});
});
Now the request looks like this:
Request URL:http://localhost:19194/ApplyBao/Apply
Request Method:POST
Status Code:400 Bad Request
Remote Address:[::1]:19194
Response Headers
view parsed
HTTP/1.1 400 Bad Request
Server: Kestrel
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNccmdiMDA3M1xEb2N1bWVudHNcYmFvYWRtaW5pc3RyYXRpb25cc3JjXEJBT0FkbWluaXN0cmF0aW9uXEFwcGx5QmFvXEFwcGx5?=
X-Powered-By: ASP.NET
Date: Thu, 12 Jan 2017 21:59:27 GMT
Content-Length: 0
Request Headers
view parsed
POST /ApplyBao/Apply HTTP/1.1
Host: localhost:19194
Connection: keep-alive
Content-Length: 580
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
Origin: http://localhost:19194
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: application/json; charset=UTF-8
Referer: http://localhost:19194/ApplyBao
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: .AspNetCore.Antiforgery.l7Q8WGuEtq8=CfDJ8K9L5D4kNnBPrb3_9Hu-w57rjjf751Qf9eh-z57qWmtMA53AB6FXsZ7pbIuLkdP2F6GjA7TGl0Tz7TfACCn3QeFt_uC-BgsYnk3Nd8z0ZA0c90XVEA90NnQOnmVFRu_KF2_2DXV89Jur84rMa-s26nQ
Request Payload
view parsed
{"info":{"HearAboutUsSelectedId":"137","FirstName":"Ron","LastName":"Bud","MiddleName":"","MaidenName":"","Email":"r@test.com","BirthDate":"1900-01-15","Phone":"123456","Fax":"","Street":"1234","City":"Denton","State":"TX","Zip":"12345","Country":"USA","SelectedExamTrack":"BCaBA","SelectedTranscriptSendMethod":"requested","Degree":"Education","SraId":"00000000-0000-0000-0000-000000000000","__RequestVerificationToken":"CfDJ8K9L5D4kNnBPrb3_9Hu-w56wPCITEDVZQo7flUIB70Pu4Q81TlRXa_oI4t8Bleou6l45oHHmUFrKusKofA6Gey-uSgKP7M3L-DrawE1TVJnrDsULHlnOE9ngg9LuyFK6-cylBJ-91h5fmaico-0yrZE"}}
The JSON now looks like a proper JSON object, but it seems my princess is in another castle. Is there something else in the pipeline that I'm missing to enable this?
UPDATE:
I finally figured it out. Turns out that the AntiForgery token was causing the request to fail, as mentioned here: POSTing complex JSON to ASP.NET Core Controller Removing that for the moment is allowing me to move forward. Thanks!