Reputation: 7194
I am having a strange issue when serializing a form to post back to a controller method. Some of the fields being passed are null (in the case of strings or nullable values) or zero (in the case of numeric values). For instance, with this simple configuration:
ViewModel:
public class HomeViewModel
{
public int FakeId { get; set; }
public string StringDataValue { get; set; }
public int IntegerDataValue { get; set; }
public HomeViewModel() { }
public HomeViewModel(int fakeId)
{
FakeId = fakeId;
StringDataValue = "This is some string data";
IntegerDataValue = 42;
}
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
HomeViewModel viewModel = new HomeViewModel(15);
return View(viewModel);
}
[HttpPost]
public JsonResult PostData(HomeViewModel model)
{
return JsonResult
{
Data = new
{
FakeId = model.FakeId,
StringData = model.StringDataValue,
IntegerData = model.IntegerDataValue
}
};
}
}
View:
@model WebApplication1.Models.HomeViewModel
@{
ViewBag.Title = "Home Page";
}
@using(Html.BeginForm())
{
@Html.HiddenFor(m => m.FakeId)
<div>
Fake ID: @Html.DisplayFor(m => m.FakeId)
</div>
<div>
String Data: @Html.TextBoxFor(m => m.StringDataValue)
</div>
<div>
Integer Data: @Html.TextBoxFor(m => m.IntegerDataValue)
</div>
<button id="btnPost">Post</button>
}
@section scripts
{
<script type="text/javascript">
$(function () {
$("#btnPost").on("click", function (e) {
e.preventDefault();
var model = $("form").serialize();
console.log(model);
$.post("PostData", JSON.stringify(model))
.success(function (d) {
console.log(d);
})
.error(function () {
console.log("error");
})
})
})
</script>
}
If I click the Post button I get this output for the two console.log()
lines:
console.log(model):
FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42
console.log(d):
Object {FakeId: 0, StringData: "This is some string data", IntegerData: 0}
As you can see only the StringDataValue actually made it to the controller. However, if I add @Html.Hidden("dummy")
in the view just above the hidden field for Model.FakeId then I get the following output:
console.log(model):
dummy=&FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42
console.log(d):
Object {FakeId: 15, StringData: "This is some string data", IntegerData: 0}
That's a little better, but the IntegerDataValue still didn't make it to the controller. However, if I add @Html.Hidden("dummy2")
somewhere after where the Model.IntegerDataValue is shown in the view I get the following output:
console.log(model):
dummy=&FakeId=15&StringDataValue=This+is+some+string+data&IntegerDataValue=42&dummy2=
console.log(d):
Object {FakeId: 15, StringData: "This is some string data", IntegerData: 42}
Now all of my view model values are being passed to the controller properly. I just don't understand why I have to put the dummy fields in to make it happen. It took me a long time to figure out why I was getting incomplete data in the controller methods until I realized what was happening.
Is it just me? Can anyone else duplicate this behavior? Am I missing something?
Upvotes: 1
Views: 319
Reputation: 2052
Take out JSON.stringify and try that. So something like
<script type="text/javascript">
$(function () {
$("#btnPost").click(function(e) {
e.preventDefault();
var model = $("form").serialize();
console.log(model);
$.post("Home/PostData", model)
.success(function(d) {
console.log(d);
})
.error(function() {
console.log("error");
});
});
});
</script>
Upvotes: 3