MVC Controller post json does not work - ajax

I have the this code to post json to a controller.
The problem is that the credentials object does not get populated with the posted values.
How do I change this code so that it works?
I see in Fiddler that the request is being posted correctly.
[HttpPost]
public JsonResult Authenticate(CredentialsModel credentials)
{
return Json(credentials);
}
[DataContract]
public class CredentialsModel
{
[DataMember(Name = "user")]
public string User;
[DataMember(Name = "pass")]
public string Pass;
}
$.ajax({
type: "POST",
url: "/login/authenticate",
cache: false,
contentType: "application/json; charset=utf-8",
data: '{"user":' + JSON.stringify($('#username').val()) + ',"uass":' + JSON.stringify($('#userpass').val()) + '}',
dataType: "json",
timeout: 100,
success: function (msg) {
},
complete: function (jqXHR, status) {
if (status == 'success' || status == 'notmodified') {
var obj = jQuery.parseJSON(jqXHR.responseText);
}
},
error: function (req, status, error) {
}
});

The default MVC model binder only works with properties. Your CredentialsModel is using fields. Try changing them to properties. You can also remove the annotations.
public class CredentialsModel
{
public string User { get; set; }
public string Pass { get; set; }
}
Also, as pointed out by Sahib, you can create a Javascript Object and then stringify it, rather than stringifying each one. Although that doesn't appear to be the problem in this case.
data: JSON.stringify({
User: $('#username').val(),
Pass: $('#userpass').val()
})

Try chaning your data like this :
$.ajax({
.................
//notice the 'U' and 'P'. I have changed those to exactly match with your model field.
data: JSON.stringify({User: $('#username').val(),Pass: $('#userpass').val()}),
.................
});

Related

MVC 5 Ajax POST - action variable not recognizing ajax data variable

I have a click function that grabs rows from an grid. The return value is a list of objects which represent each row. I use JSON.stringify so I can send the data to my SaveJobs action on my Home Controller. The following properties work and my controller action recognizes the data, but it is not in valid JSON format.
contentType: 'application/json; charset=utf-8'
data: { data: JSON.stringify(editedRows) }
However, I found through research that the below method is preferred since it is a valid JSON format, but my data variable on my controller action is null (returning no data to perform my action on) and I could not debug the issue. Why does the action variable not recognize this? Thank you.
$('#SaveJobs').on('click', function () {
editedRows = getEditedRows();
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: savePlannedJobsUrl,
cache: false,
data: JSON.stringify({ data: editedRows }),
dataType: "text",
success: function (result) {
if (result === 'Success') {
alert('The records you have edited are saved');
}
else {
alert('There was an error with the server. All records may not have been saved.');
}
$("*").css("cursor", "");
},
error: function (HtmlHttpRequest, ajaxOptions, thrownError) {
var htmlObj = $.parseHTML(HtmlHttpRequest.responseText);
var savedJson = JSON.stringify(editedRows);
if (htmlObj !== null) {
var htmlBody = htmlObj[htmlObj.length-1].outerText;;
}
tryToWriteError(htmlBody, savedJson);
}
});
return false;
});
Controller
[HttpPost]
public string SaveJobs(string data)
{
// CODE HERE
}
ANSWER:
I marked #Queti's answer, and more specific to my problem see the link in my comment that will help for MVC projects. That resolution will skip creating DTOs.
The issue is that you are sending in an array of objects, but your action method is expecting a string.
It appears that your getEditedRows method is returning an array of objects.
I recommend you create a model on the server that matches what you are passing in. Something like:
public class MyDto
{
int id { get; set; }
string comments { get; set; }
}
And then update your method signature to accept that as the parameter:
public string SaveJobs(List<MyDto> data)

JSON and ASP.Net MVC Controller is not binding the properties of the list of objects

I am making an AJAX call with jQuery:
var topic = new Array();
$('.container-topico').each(function (i) {
topic.push(
{
"TopicsModel":
{
begins: $(this).find('.HoursStart').val(),
ends: $(this).find('.HoursEnd').val(),
texts: $(this).find('.input-topic').val()
}
}
);
});
var data = JSON.stringify({
videoId: '<%=Url.RequestContext.RouteData.Values["id"]%>',
topics: topic
});
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: '<%= Url.Action("SubmitTopics") %>',
traditional: true,
data:
data
,
beforeSend: function (XMLHttpRequest) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
},
success: function (data, textStatus, XMLHttpRequest) {
$(data).each(function () {
});
}
});
It is sending the JSON in the format (e.g):
{"videoId":"1","topics":
[{"TopicsModel": {"begins":"00:00:33","ends":"00:01:00","texts":"1. Primeiro tema"}},
{"TopicsModel": {"begins":"00:01:00","ends":"00:01:33","texts":"2. Segundo tema"}},
{"TopicsModel": {"begins":"00:01:33","ends":"00:02:00","texts":"3. Terceiro tema"}},
{"TopicsModel": {"begins":"00:02:00","ends":"00:00:21","texts":"dasdasdsa ada as das s"}},
{"TopicsModel": {"begins":"0","ends":"0","texts":""}}]}
And on the server side it has the Model:
public class TopicsModel
{
public string begins;
public string ends;
public string texts;
}
and the Controller:
public ActionResult SubmitTopics(int videoId, List<TopicsModel> topics)
What happen is:
It have the correct number of objects, but is not binding the properties of each element, as you can see bellow:
Why is it not binding to the properties ?
The binding can't find the TopicsModel property in your TopicsModel object, so it can't bind the value.
Try this instead :
{"videoId":"1","topics":
[{"begins":"00:00:33","ends":"00:01:00","texts":"1. Primeiro tema"},
{"begins":"00:01:00","ends":"00:01:33","texts":"2. Segundo tema"},
{"begins":"00:01:33","ends":"00:02:00","texts":"3. Terceiro tema"},
{"begins":"00:02:00","ends":"00:00:21","texts":"dasdasdsa ada as das s"},
{"begins":"0","ends":"0","texts":""}]}
The binding should then resume normally.
You also have to change your model this way :
public class TopicsModel
{
public string begins { get; set; }
public string ends { get; set; }
public string texts { get; set; }
}
Try re-naming List<TopicsModel> topics in the controller parameter list to List<TopicsModel> model

Pass List from view to controller

i am trying to pass List from view to controller but i am getting null value. code is written as follows :
model class :
public class testModel
{
public int ID { get; set; }
public string Name { get; set; }
public List<myModel> ParameterList {get;set;}
}
jquery and ajax code to post data to controller :
var myModel = {
"Name":"test",
"Description":"desc"
};
var Object = {
Name: $("#Name").val(),
ParameterList : myModel
};
$.ajax({
url: '/controller/action',
type: 'POST',
data: JSON.stringify(Object),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) { }
else { }
}
});
i am getting value for Name property but not for ParameterList.
What is wrong here ? am i missing anything ?
Please help me out.
Thanks
Edit : Controller Code from comments,
public JsonResult Save(Object Obj)
{
// logic for managing model and db save
}
You said,
I am getting value for Name property but not for ParameterList.
Which makes me wonder what is the structure of myModel, as you have declared ParameterList as a list of myModel type : List<myModel> ParameterList
Also I would recommend you to log JSON.stringify(Object) to console and check the Json value you are actually posting to the controller.
Here is what I found you must be posting back
{"Name":"yasser","ParameterList":{"Name":"test","Description":"desc"}}
Also read these articles :
How can I pass complex json object view to controller in ASP.net MVC
Pass JSON object from Javascript code to MVC controller
Try this:
var myModel = [{
"Name":"test",
"Description":"desc"
}];
var Object = {
Name: $("#Name").val(),
ParameterList : myModel
};
$.ajax({
url: '/controller/action',
type: 'POST',
data: Object,
dataType: 'json',
traditional: true,
contentType: 'application/json; charset=utf-8',
success: function (data) { }
else { }
}
});
Just try like this..Hope this would help!!
script:
var emp = [{ 'empid': 1, 'name': 'sasi' },{ 'empid': 2, 'name': 'sathish'}];
emp = JSON.stringify(emp)
$.post("/Home/getemplist/", { 'emp': emp })
Controller:
Here i just changed the parameter to string type. using JavaScriptSerializer you can able to convert this string data to your class list objects.. you can understand it better if u see my code below:
public void getemplist(string emp)
{
List<Emp> personData;
JavaScriptSerializer jss = new JavaScriptSerializer();
personData = jss.Deserialize<List<Emp>>(emp);
// DO YOUR OPERATION ON LIST OBJECT
}

Nested models don't bind

I want to pass a JSON data structure to an MVC (3) Controller, have the JSON object be translated into a C# object, with all properties bound. One of the properties is a simple Type. That's basic model binding, right?
Here are my models:
public class Person
{
public string Name { get; set; }
public JobTitle JobTitle { get; set; }
}
public class JobTitle
{
public string Title { get; set; }
public bool IsSenior { get; set; }
}
Here is my Index.cshtml page (which makes an AJAX request, passing in a JSON object which matches the strcture of the "Person" class):
<div id="myDiv" style="border:1px solid #F00"></div>
<script type="text/javascript">
var person = {
Name: "Bob Smith",
JobTitle: {
Title: "Developer",
IsSenior: true
}
};
$.ajax({
url: "#Url.Action("ShowPerson", "Home")",
data: $.param(person),
success: function (response){
$("#myDiv").html(response);
},
error: function (xhr) {
$("#myDiv").html("<h1>FAIL</h1><p>" + xhr.statusText + "</p>");
}
});
</script>
And my HomeController looks like this:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult ShowPerson(Person person)
{
return View(person);
}
}
Ignore the "ShowPerson.cshtml" file for now because the problem occurs before that is ever needed.
In the HomeController.ShowPerson action, the "person.Name" property is correctly bound and the "person.JobTitle" object (containing "Title" and "IsSenior" properties) is instantiated but still has the default values of "Title = null" and "IsSenior = false".
I'm sure I have done nested model binding without problem in the past. What am I missing? Can anybody shed any light on why model binding only seems to work one level deep?
I've searched SO, and it seems everybody else is having binding problems when sending data from forms, so maybe I'm missing something in my $.ajax() request?
ok, there are couple of changes you need to do,
Set dataType as json
Set the contentType as application/json; charset=utf-8.
Use JSON.stringify()
below is the modified code. (tested)
var person = {
Name: "Bob Smith",
JobTitle: {
Title: "Developer",
IsSenior: true
}
};
var jsonData = JSON.stringify(person);
$.ajax({
url: "#Url.Action("ShowPerson", "Home")",
data: jsonData,
dataType: 'json',
type: 'POST',
contentType: "application/json; charset=utf-8",
success: function (response){
$("#myDiv").html(response);
},
error: function (xhr) {
$("#myDiv").html("<h1>FAIL</h1><p>" + xhr.statusText + "</p>");
}
});
Add the content type to the ajax
contentType: "application/json; charset=utf-8",
dataType: 'json',
type: 'POST',
data: $.toJSON(person);

MVC3 jquery ajax parameter data is null at controller

I have a controller action that I want to update via a jquery call. The action runs, but there is no data in the parameters.
I am using a kedoui grid with a custom command in a column that I want to run some server code.
kendoui grid in view
...
columns.Command(command =>
{
command.Custom("ToggleRole").Click("toggleRole");
});
...
The model is of type List<_AdministrationUsers>.
public class _AdministrationUsers
{
[Key]
[ScaffoldColumn(false)]
public Guid UserID { get; set; }
public string UserName { get; set; }
public string Role { get; set; }
}
Here is my toggleRole Script:
<script type="text/javascript">
function toggleRole(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
alert(JSON.stringify(dataItem));
$.ajax({
type: "POST",
url: '#Url.Action("ToggleRole", "Administration")',
data: JSON.stringify(dataItem),
success: function () {
RefreshGrid();
},
error: function () {
RefreshGrid()
}
});
}
</script>
Here is my controller action:
[HttpPost]
public ActionResult ToggleRole(string UserID, string UserName, string Role)
{
...
}
The controller action fires, but there is no data in any of the parameters.
I put the alert in the javascript to verify that there is indeed data in the "dataItem" variable. Here is what the alert text looks like:
{"UserID":"f9f1d175...(etc.)","UserName":"User1","Role","Admin"}
Did you try specifying the dataType and contentType in you ajax post ?
$.ajax({
type: "POST",
url: '#Url.Action("ToggleRole", "Administration")',
data: JSON.stringify(dataItem),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () {
RefreshGrid();
},
error: function () {
RefreshGrid()
}
});
It looks like you are posting the whole object as one Json string, while the controller expects three strings. If you are using MVC3 the parameter names also have to match the controllers signature. Try to parse up your data object so that it matches the input expected from the controller. Something like this:
$.ajax({
type: "POST",
url: '#Url.Action("ToggleRole", "Administration")',
data: { UserID: dataItem.UserID, UserName: dataItem.UserID, Role: dataItem.Role },
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () {
RefreshGrid();
},
error: function () {
RefreshGrid()
}
});
Hope that helps!
{"UserID":"f9f1d175...(etc.)","UserName":"User1","Role","Admin"}
Seems incorrect to me. Wouldn't you want this?
{"UserID":"f9f1d175...(etc.)","UserName":"User1","Role" : "Admin"}
Notice the "Role" : "Admin"

Resources