Reputation: 4020
In my MVC view model, I have a table, inside a form.
From my javascript, I'm invoking my controller as follows:
$.ajax(
{
type: "POST",
url: "@Url.Action("ReorderClues", "Clues", Model)",
data: JSON.stringify(positions),
contentType:'application/json'
});
And my controller signature is as follows:
public ActionResult ReorderClues(TreasureHuntDetails treasureHuntDetails, int[] ids)
What I find is that when the javascript invokes the controller in this way, the data model (the TreasureHuntDetails object) is populated with only the treasureHuntId, and everything else is null. The second parameter, the ids array populates successfully - this is the one that I use JSON.stringify() on in the ajax function.
I can't figure out why everything else is null apart from the treasureHuntId. In the form, I have a HiddenFor line for every property of the object, like this:
@Html.HiddenFor(m => m.CompletionMessage)
@Html.HiddenFor(m => m.Description)
@Html.HiddenFor(m => m.Clues)
@Html.HiddenFor(m => m.Leaderboard)
@Html.HiddenFor(m => m.TreasureHuntId)
etc.
I don't see what's special about the TreasureHuntId variable that it is the only one whose value is the only populated one on the object which reaches the controller. Any ideas? What could I be doing wrong?
When I invoke the controller the normal way with just the data model (TreasureHuntDetails), everything gets populated properly, so it's only in the javascript where I'm also adding on the Ids array (the 'positions' variable in the javascript code snippet is an integer array).
Upvotes: 1
Views: 1691
Reputation: 4632
This is working for me, I've left the original post below:
$.ajax({
type: 'POST',
contentType: 'application/json',
url: '@Url.Action("Contact", "Home")',
data: JSON.stringify({
completionMessage: $("#CompletionMessage").val(),
description: $("#Description").val(),
clues: $("#Clues").val(),
leaderboard: $("#Leaderboard").val(),
treasureHuntId: $("#TreasureHuntId").val(),
ids: positions
})
});
You need to remove the 'Model' from your Url.Action() and of course change the values from my sample to the action and controller name you are using. I've included the 'positions' variable just to make it clear, your value will come from outside of this closure.
--- Original Answer ---
You need to include all of the hidden values in the data that you pass for your AJAX call. What you have written is working as you have written it, but the additional form values from your page are not going to be included. If I had to guess, if the TreasureHuntId is an integer then it is populated with the first value in the array from the positions variable. What you might want to do is put Fiddler in and watch what is getting posted.
Take a look at the source in the browser for your URL. It might surprise you on how that looks compared to what you are expecting. Are you depending on the default route for this? Check out if you've made any special route for this action in the controller.
I think the best method is to create the object manually: jQuery documentation on AJAX specifies that the data setting is either a serialized query string or an object. If you use an object then you will likely want to change the dataType to 'json', you don't need a contentType.
data: {
CompletionMessage: $('#CompletionMessage').val(),
Description: $('#Description').val(),
// other fields here...
ids: JSON.stringify(positions)
}
Note you may need/want to change the signature on the controller to accept individual parameters vs the TreasureHuntDetails class if it doesn't identify the method.
Alternatively, take a look at the serialize() function in jQuery - the documentation on the $.post() will help you toward a solution. Keep in mind if you go this route then you need to remote the contentType as it defaults to the correct form MIME type.
Upvotes: 1
Reputation: 7215
I had the situation earlier this year where it was because my jQuery variable name was not the same as my actionresult parameter name. Don't ask why, but that was the problem for me.
Upvotes: 0
Reputation: 56429
You're not actually passing your model back. The reason the ID is in there is probably because it was already in the url on the HttpGet request.
First, change your url to not have the model on it:
url: "@Url.Action("ReorderClues", "Clues")",
Then change your ajax method to pass the model back too:
data: { treasureHuntDetails: $("form").serialize(), ids: JSON.stringify(positions) }
Upvotes: 2