I currently have a ajax request setup to send a "PUT" request to a web api in my mvc 4 project. My request is able to get into the method on the api but the parameter is always null. Any ideas why? I have also check the PUT request as its executed and it does send a string of key/value pairs for each form control. Here is my code:
Web Api method (selection is always null)
public void Put([FromBody]string selection)
{
}
Update:
I forgot I was doing a little debugging of my own. I have confirmed that when you serialize a form the param is named "selection". Please take another look.
Ajax call:
$.ajax({
type: "PUT",
url: urlPrefix + "api/file/Manipulate",
data: $("#frmManipulate").serialize(),
contentType: "application/json; charset=utf-8",
dataType: "json",
statusCode: {
204: function (jqXHR) {
alert("No file(s)/Directory(s) were selected.");
}
}
}).done(function () {
location.reload();
});
It's null because you aren't passing it:
data: { val1 : "test", val2 : "test2"}
Try:
data: { selection : "something" }
It is null because asp.net web api does not know how to deserialize the { val1 : "test", val2 : "test2"} to a string. You could use a DTO approuch to pass these information to the action, for sample:
in the web api project, add a class like this:
public class InfoDTO
{
public string val1 { get; set; }
public string val2 { get; set; }
// other properties if you need
}
And change your put action to get a parameter with this type:
public void Put([FromBody]InfoDTO info)
{
// use 'info' object
}
Your client-side javascript can keep with the same code.
Related
I am trying to pass a single boolean value via ajax to a server API.
The API action is hitted but the parameter (shuffled) is false, though I am setting it to true via Ajax.
The api controller action is this:
[HttpPost("PostShuffled")]
public IActionResult PostShuffled([FromBody]bool shuffled)
{
userSession.Shuffled = shuffled;
return Ok();
}
My Ajax call is this:
function ChangeViewMode(el) {
if (el.id == "ViewShuffled") {
$.ajax({
url: "/api/Data/PostShuffled",
contentType: "application/json",
method: "POST",
data: JSON.stringify({ shuffled: true }),
success: function () { alert("ok"); }
});
}
}
My question is what am I doing wrong?
Ok I have solved the problem this way:
Defined a new class:
public class AjaxShuffled
{
public bool shuffled { get; set; }
}
Then in my controller changed:
[HttpPost("PostShuffled")]
public IActionResult PostShuffled([FromBody]AjaxShuffled s)
{
userSession.Shuffled = s.shuffled;
return Ok();
}
And now the value is passed correctly. I had to encapsulate the boolean into a class to make it work.
The problem is that shuffled is wrapped in an object instead of sent by itself. If you only want to send a boolean value, just send true or false itself: data: true or data: JSON.stringify(true) depending on how you've configured your web service to handle input formats for boolean. On the server side you should only need the [FromBody] descriptor on the API method parameter.
I have a situation where I get data from ajax call. I want to call an action method and pass data as arguments. The data passed to action method should be mapped to object properties in parameter list.
Here is my class which is called FullQuestion.
public class FullQuestion : Question
{
public string Title { get; set; }
public string Content { get; set; }
public List<Tag> Tags { get; set; }
}
Here is my Ajax call method
var finalTagResultText = {Title: "title", Content: "content",Tag: { tagName: "tname", tagDescription: "tdesc"},Tag: { tagName: "tname1", tagDescription: "tdesc1"}};
$.ajax({
url: '#Url.Action("AskQuestion", "Dashboard")',
type: "POST",
data: JSON.stringify(finalTagResultText),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
window.location.href = "#Url.Action("Questions", "Dashboard")";
}
});
Here is my action method.
[HttpPost]
[ActionName("AskQuestion")]
public void AskQuestion_Post(FullQuestion question)
{
}
I want to get the JSON object passed as a FullQuestion object. I used json2 library to make use of stingify method.
I get the title and content text but no Tag object.
Any idea how can i accomplish that ? Thanks in advance.
Your collection property is named Tags (not Tag) and since its a collection, you need to pass an array of Tag objects, for example
var finalTagResultText = { .... , Tags: [{ tagName: "tname", tagDescription: "tdesc"}, { tagName: "tname1", tagDescription: "tdesc1"}]}`
Side note: Your ajax success callback is redirecting to another page, in which case, do not use ajax to submit your data. The whole point of ajax is to stay on the same page. You would be better off just doing a standard submit and using a RedirectToAction() in your POST method.
You are using wrong JSON format, using correct format as follows:
{"Title": "title", "Content": "content","Tag":[{ "tagName": "tname", "tagDescription": "tdesc"},{ "tagName": "tname1", "tagDescription": "tdesc1"}]}
In order to verify your JSON string, you can use the below link
https://jsonformatter.curiousconcept.com/
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.
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)
I am using revealing module pattern and knockout to bind a form. When data is entered in that form(registration), it needs to be posted back to MVC4 web method.
Here is the Jquery code
/*
Requires JQuery
Requires Knockout
*/
op.TestCall = function () {
// Private Area
var _tmpl = { load: "Loading", form: "RegisterForm"};
var
title = ko.observable(null)
template = ko.observable(_tmpl.load),
msg = ko.observable(),
postData = ko.observable(),
PostRegistration = function () {
console.log("Ajax Call Start");
var test = GetPostData();
$.ajax({
type: "POST",
url: obj.postURL, //Your URL here api/registration
data: GetPostData(),
dataType: "json",
traditional: true,
contentType: 'application/json; charset=utf-8'
}).done(Success).fail(Failure);
console.log("Ajax Call End");
},
GetPostData = function () {
var postData = JSON.stringify({
dummyText1: dummyText1(),
dummyText2: dummyText2(),
});
return postData;
}
return {
// Public Area
title: title,
template: template,
dummyText1: dummyText1,
dummyText2: dummyText2
};
}();
The controller code is simple as per now
// POST api/registration
public void Post(string data)
{
///TODO
}
When i am trying to, capture the data (using simple console.log) and validate it in jslint.com, it's a valid Json.
I tried hardcoding the data as
data: "{data: '{\'name\':\'niall\'}'}",
But still i get as null, in my web method.
Added the tag [System.Web.Script.Services.ScriptMethod(UseHttpGet = false, ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] to my Post method in controlled, but still no fruitful result
Even tried JSON.Stringify data: JSON.stringify(data) but still i get null in my web-method.
I am not able to figure out the solution.
Similar issue was found # this link
http://forums.asp.net/t/1555940.aspx/1
even Passing parameter to WebMethod with jQuery Ajax
but didn't help me :(
MVC and WebApi uses the concept of Model Binding.
So the easiest solution is that you need to create a Model class which matches the structure of the sent Json data to accept the data on the server:
public void Post(MyModel model)
{
///TODO
}
public class MyModel
{
public string DummyText1 { get; set; }
public string DummyText1 { get; set; }
}
Note: The json and C# property names should match.
Only escaped double-quote characters are allowed, not single-quotes, so you just have to replace single quotes with double quotes:
data: "{data: '{\"name\":\"niall\"}'}"
Or if you want to use the stringify function you can use it this way:
data: "{data: '" + JSON.stringify(data) + "'}"