How to pass List<T> from from JS to API - ajax

I have below model and Controller. I want to know how to pass value for the API from Ajax call.
Model:
Public Class Data
{
public int ID {get;set;}
public string Title {get;set;}
}
Controller:
[HTTPPOST]
public string UpsertItems(List<Data> Inputs)
{
try
{...}
catch(Exception ex)
{..}
}
From frontend i need to pass below data to API.
I tried passing data like below
var datacoll='{{"ID":1,"Title":"a"},{"ID":2,"Title":"b"}}'
If I pass variable datacoll as it is I am getting 500 internal error and if I pass JSON.Stringify(datacoll) in controller i am getting null value.
Ajax method:
$.ajax({
url: '/Test/UpsertItems',
method: 'POST',
dataType: 'text',
contentType: 'application/json; charset=utf-8',
data: datacoll,
success: function (data) {..},
error: function (jqXHR) {..},
});
Please let me know what is wrong in it.

Looks like your data needs to be a list, notice the square brackets.
var datacoll='[{"ID":1,"Title":"a"},{"ID":2,"Title":"b"}]'

Related

Ajax sending variable value to MVC controller

I am trying to send a value from jQuery using ajax call and fetch the value in the controller. Below is what I am trying, but the value of A is always null. Can someone help me where I am going wrong.
$.ajax({
type: "POST", //The type of Method being used (GET, SET, POST, etc.)
url: '/Controller1/Index',
contentType: 'application/json; charset=utf-8',
data: { A: "true" }, //Your data to pass to your Controller action
dataType: "json",
success: function (result) {
alert(response.responseText);
alert("Done!");
}
});
C# code
[HttpPost]
[ActionName("Index")]
public ActionResult IndexPost(FilterRule queryBuilder, BootstrapTableQueryType bootstrapTable, string A)
{
string B = A;
}

Parameters not populating with Ajax Call

This is my controller
[HttpPost]
public bool Sync(int? id, string name)
{
throw new NotImplementedException();
}
Here is my ajax request call that I am trying to make to this controller:
<script type="text/javascript">
var buttonClicked = document.getElementById("syncLegacy");
buttonClicked.addEventListener('click', function () { syncLegacyMake(); }, false);
function syncLegacyMake() {
$.ajax({
url: '/Legacy/Sync',
type: 'POST',
data: JSON.stringify({
id: $("#Id").val(),
name: $("#Name").val()
}),
contentType: 'application/json; charset=utf-8',
success: function (data) {
},
error: function () {
alert("error");
}
});
}
The controller gets hit however there are no values to the parameters. The values are both null.
When I look at the call itself on chrome console, the values are populated as these under Request Payload in the headers:
{id: "01", name: "Titan"}
id
:
"01"
name
:
"Titan"
Could anyone point out what I am doing wrong here? I have been able to do the same in .net 4.6.1 framework so not sure if framework changed has caused this?
have you tried the following things:
Using a Dto instead of separate simple types:
public class SyncDto
{
public int? Id {get;set;}
public string Name {get;set;}
}
// Controller action:
[HttpPost]
public bool Sync(SyncDto input)
{
throw new NotImplementedException();
}
Make Jquery stringify itself
Let jquery figure your ajax call out itself:
$.ajax({
url: '/Legacy/Sync',
type: 'POST',
data: {
id: $("#Id").val(),
name: $("#Name").val()
}
});

MVC web api GET parameter is always null

Following is my ajax call
$.ajax({
type: "GET",
url: "https://localhost/api/Client",
data: JSON.stringify({"SortExpression":"clientName","SortDirection":"desc"}),
contentType: "application/json; charset=utf-8",
async: false,
cache: false,
dataType:'json',
error: function (data) {
alert("hi error buddy")
},
success: function (response) {
if (response) {
//todo
}
}
});
And my controller
public List<Customer> Get([FromUri] SortFilter filter)
{
}
and my model
public class SortFilter
{
public string SortExpression
{
get; set;
}
public string SortDirection
{
get; set;
}
}
but my contoller always takes the parameters as NULL. where am I going wrong ?
You're supplying a value, but not a key. So while the model binder may be able to discern what a SortFilter is, it has no way of knowing what filter is.
Try wrapping the object and giving it a key name. Perhaps something like this:
JSON.stringify({"filter":{"SortExpression":"clientName","SortDirection":"desc"}})
GET requests are performed on the query string, which should not be JSON encoded. POST, and PUT data may be JSON encoded, but not GET. The reason your parameter is null is because the query string is a single string with no parameter name.
replace:
data:JSON.stringify({"SortExpression":"clientName","SortDirection":"desc"})
with
data:{"SortExpression":"clientName","SortDirection":"desc"}
You can check the WebAPI call directly by typing in the full URL to the web API method
https://localhost/api/Client?SortExpression=clientName&SortDirection=desc
This will allow you to debug your data retriever, and page separately which should make the whole process much easier.

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)

AJAX & ASP.NET MVC 3: How to pass a string parameter AND an array at the same time to Controller

I have the following Controller signature:
public void DoSomething(string dialerJob, MyViewModel[] agentStates)
The viewModels represent form fields in an array (selected items in an HTML table). I figured out how to pass the form elements int as an array argument to the controller thanks to Robert Koritnik's .toDictionary() jQuery plug-in (http://erraticdev.blogspot.com/2010/12/sending-complex-json-objects-to-aspnet.html).
However, now I need to pass one additional string parameter (from a dropdown) to the controller and I cannot figure out how to make that work. I've tried various combinations, like:
var job = $('#DialerJobs').attr('value');
var data1 = $.toDictionary(data, "agentStates");
$.ajax({
url: "/Blending/ChangeOutboundJob",
type: "POST",
dataType: "application/JSON",
data: {job, data1}
});
I've also tried the following:
var job = $('#DialerJobs').attr('value');
var data1 = $.toDictionary(data, "agentStates");
$.ajax({
url: "/Blending/ChangeOutboundJob",
type: "POST",
dataType: "application/JSON",
data: {dialerJob: job, agentStates: data1}
});
But neither work.
If I remove the dialerJob parameter from the data to send, the agentStates populate in the controller correctly. And what gets sent looks like this:
agentStates[0].agentId=7654&agentStates[0].projectId=999&agentStates[0].stateId=1&agentStates
[0].subStateId=1&agentStates[1].agentId=9876&agentStates[1].projectId=999&agentStates
[1].stateId=1&agentStates[1].subStateId=1
But if I included the dialerJob, then what gets sent is:
dialerJob=SomeJob&agentStates[0][name]=[0].agentId&agentStates[0][value]=84&agentStates[1][name]=
[0].projectId&agentStates[1][value]=999&agentStates[2][name]=[0].stateId&agentStates[2][value]
=1&agentStates[3][name]=[0].subStateId&agentStates[3][value]=1&agentStates[4][name]=[1].agentId&agentStates
[4][value]=15884&agentStates[5][name]=[1].projectId&agentStates[5][value]=999&agentStates[6][name]=[1].stateId&agentStates[6][value]=1&agentStates[7][name]=[1].subStateId&agentStates[7][value]=1
Which is all messed up...
You could use a JSON request:
$.ajax({
url: '#Url.Action("ChangeOutboundJob", "Blending")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
dialerJob: 'job',
agentStates: [
{ property1: 'value 1', property2: 'value 2' },
{ property1: 'value 3', property2: 'value 4' }
]
}),
success: function (result) {
// TODO: process the results
}
});
This will successfully map to the following controller action:
public void DoSomething(string dialerJob, MyViewModel[] agentStates)
where MyViewModel is defined like this:
public class MyViewModel
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
Remark: the JSON.stringify method is natively built into all modern browsers. If you need to support legacy browsers you need to include the json2.js script into your page.
change the js job var to be called dialerJob, the names must match for the mapper to auto map them.

Resources