Can't pass serialized Json to Web API action - c#

NOTE Please see the update at the bottom.
I'm picking up maintenance on an existing (working) application.
The application receives data into a class via a post to a Web API controller action.
However when I try to test this by posting it some data it just gives an empty object.
I assumed that my Json must be wrong so I tried sending the Json string as text and deserializing manually, and this works fine, returning the populated object I would expect to see.
I've searched online and seen various suggestions about adding attributes to the parameters but this doesn't do it for me.
The code looks pretty much as follows:
[HttpPost]
[AllowBasicAuthentication]
public async Task<MyResponse> ProcessData(
[FromUri]string key,
[FromUri]string name,
[FromUri]string value1,
[FromBody] DataClass value // this is never populated
)
{
// the following returns the data as expected
var test = new JavaScriptSerializer().Deserialize<DataClass>(value1);
...
}
The jQuery I'm using to test this is as follows:
$('#post').click(function () {
var key = $('#key').val();
var name = $('#name').val();
var value1 = $('#value').text();
var value = JSON.parse(value1);
var url = '/api/ProcessData/?key=' + key
+ '&name=' + name
+ '&value1=' + value1
/* with this post value appears in action as an instantiated but empty object */
$.post(url, { value: value })
.success(function (r) {
...
})
.fail(function (r) {
...
})
/* also tried the following, but value appears as null object
$.ajax({
url: url,
type: 'POST',
cache: false,
contentType: "application/json",
data: value,
success: function (r) {
alert(r);
}
});
*/
});
[EDIT]
Just to clarify, I added the value1 string parameter to test that the Json can be deserialized correctly, which it can, so the Json is ok and the class is ok.
UPDATE
This works when called from Postman so the error must be in the jQuery.
Can anyone show the correct way to do this?
Thanks
[/EDIT]

Related

HttpContext.Request.Form.Keys is empty when HttpContext.Request.HasFormContentType = true

This was working 2 days ago and now it's not and I cannot figure out why. I am submitting form data via ajax:
var mData = 'item=' + itemid + '&action=' + action;
$.ajax({
url: "/Admin/Home/Ajax",
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: mData,
success: function (data) {
//Do Something
}
});
I have a method that process the incoming post:
if (HttpContext != null && HttpContext.Request.HasFormContentType)
{
foreach (var key in HttpContext.Request.Form.Keys)
{
QueryParams.Add(key, HttpContext.Request.Form[key]);
}
}
When the data is posted, HttpContext.Request.HasFormContentType is equal to true however, HttpContext.Request.Form.Keys.Count is equal to 0
I get no errors or anything. Any help or insight as to what is going on would be greatly appreciated.
This is a dotnet core 2.2 mvc web app.
Here is a working demo like below:
1.View:
<script>
var mData = 'item=' + 1 + '&action=' + "aaa";
$.ajax({
url: "/Home/Ajax",
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: mData,
success: function (data) {
//Do Something
}
});
</script>
2.Action:
[HttpPost]
public void Ajax(int item,string action)
{
if (HttpContext != null && HttpContext.Request.HasFormContentType)
{
foreach (var key in HttpContext.Request.Form.Keys)
{
}
}
}
3.Result:
You are sending query data, not form data. Try sending it in a form like:
{
item: ...,
action: ...
}
Edit: Actually I was a bit surprised that it works while sending raw type of data and then passing in the query-like string. But the mearly fact that it works it doesn't mean it is a proper way of doing things. Foe example if You try to send API request from Postman (which I tried to reproduce Your error) I wasn't even able to perofrm such a thing as Postman asked me for key value pairs and interpreted a given query as a one key. Besides sending js object is more simpler that building a string.
I was also facing the issue of HttpContext.Request.Form.Keys is empty.
I just removed the .aspx extension from the request page and now the problem seems to be resolved for me.

mvc controller pameter getting null value in ajax call

I am making ajax call like this
deleteAge(item: any): string {
$.ajax({
method: "POST",
url: 'DeleteAge',
data: item.Id(),
success: (response) => {
toastr.success("ready soon");
},
error: (event) => {
toastr.error("Error occured ");
}
}).always(() => {
});
return "";
}
Here is my method in controller which is currently nothing almost implemented
[HttpPost]
public ActionResult DeleteAge(string id)
{
throw new Exception();
}
when i run the code then in my controller i dont get any id.. its null. when i debug my javascript code then this code item.Id() is not blank. Even if i pass hardcoded value to data in ajax call still controller gets null. What is wrong?
Rather than using:
data: item.Id(),
I'd suggest using:
data: { id: item.Id()},
This way the id value is associated with the id name - allowing model binding to work correctly.
Pass parameters like json format in ajax
replace data: item.Id() with data: {id: 1}

ASP.NET / jQuery : post JSON to web-service

I'm trying to post some JSON to a web service. The web-service is executed but there's no data available.
The jQuery looks like this :
var json = {"Results": results};
var jsonArray=JSON.stringify(json);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: requestURL,
data: jsonArray ,
dataType: "json",
success: function (data) { TCG.QUE.processSaveButtonSucceeded(data); },
error: function (data) { TCG.QUE.processSaveButtonFailed(data); }
});
And the webservice implemented in a controller looks like this :
public HttpResponseMessage Post([FromBody]string value)
{
object o1 = Request.Content;
HttpResponseMessage r = new HttpResponseMessage(HttpStatusCode.OK);
return r;
}
If I take out the [FromBody] directive then I get a 404. If I leave it in the code is executed but the value of the value argument is null.
I thought the [FromBody] directive meant the data was contained in the Request object but if it is I can't find it .
Would appreciate any suggestions so that I can access the JSON from the client within the Post method.
UPDATE:
I just re-read this : http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api which made me wonder whether the name I was giving the JSON blog client side should correspond to the name of the argument on which the [FromBody] is applied so I changed the name of the argument from value to Results but still the value within the Post method is null.
RESOLUTION
After reading the blog post referred to by Prashanth Thurairatnam I changed my method to be like this and it works :
public HttpResponseMessage Post([FromBody]JToken jsonbody)
{
// Process the jsonbody
return new HttpResponseMessage(HttpStatusCode.Created);
}
.
Not sure what you are passing into results. Ran into this blog. You may want to give it a go. The blog talks on passing the data as JSON object/ array (you may want to try without JSON.stringify)

Adding JSON to a List in my Controller

I have seen a lot of posts that seem to somewhat address my situation but they all leave me a bit confused.
I have an object that I am POSTing to my Controller. I have the post coming to my controller okay by doing this:
$('#fileSubmit').click(function () {
var filesObj = [];
$('#fileList .files .fileName').each(function () {
var name = $(this).text();
filesObj.push({ 'name': name });
});
$.ajax({
type: "POST",
url: "/FileUpload/ImportCommit",
data: filesObj,
dataType: "json"
});
});
I want to then take that JSON object and put it into a list in my controller. So far here is what i have, but I have not done a lot of coding in C# and don't know what to do next.
[HttpPost]
public ActionResult ImportCommit(List<string> filenames)
{
}
I know my controller method's code is blank, but am not sure what to do next. Any help would be much appreciated. Thanks!
The post data you send via the data field of the ajax method needs to be name value pairs. Asp.Net will map them in the Request Params collection via their name. E.g. if you post an object like this,
{
fileNames: JSON.stringify(arFileNames)
};
It can then be accessed server side via,
string json = HttpContext.Current.Request.Params["fileNames"];
If your json looks something like this,
"{"filenames":["somefile","somefile2","somefile3"]}"
You could use newtonsoft JSON (JSON.Net) to convert it to a list of strings by creatong a class to represent it, like this,
public class JsonResultFileNames
{
[Newtonsoft.Json.JsonProperty(PropertyName = "filenames")]
public string[] FileNames { get; set; }
}
Then convert the json to JsonResultFileNames with,
JsonResultFileNames jsonResult = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonResultFileNames>(jsonStringHere);
Then you have a c# object representing your json data. Also you can get way more complex with this, but the important thing to note with JSON.Net, is it quite literally deserializes into a c# representation. E.g. if you want to deserialize straight to a string array, then there should only be an array of strings in your json (no object/field names etc).
E.g. where I work we have an api that returns results like this,
{
status: {
success: true;
},
customerdata {
id: {some-guid},
name: Some Customer Name
}
}
The problem with that, is my C# class needs to be composed of nested classes, e.g. I need a class to represent status and a class to represent customerdata. Things can get weird naming wise when doing that, I ended up with things like CustomerResponse, CustomerResponseStatus, CustomerResponseData, where CustomerResponseStatus and CustomerResponseData are exposed in CustomerRespnose, and I deserialize the json to the CustomerResponse type.
If your json is just an array of strings, you should be able to use string[] for the type passed into JsonConvert.Deserialize, which would not require you to make response classes to hold the data.
The trick was to modify my AJAX to POST like this:
$.ajax({
type: "POST",
url: "/dat/Controller",
data: JSON.stringify(filesObj),
contentType: "application/json",
traditional: true,
success: function (result) {
console.log("Success: " + result);
},
error: function (result) {
console.log("Error: " + result);
}
});
Changing dataType to contentType and adding traditional: true seemed to do the trick for me. The reason for this (I believe) is because the actual data that I was posting is technically not JSON. I added the traditional: true just to be on the safe side.

JQuery values passed to WebApi is always null

I am having trouble with Web Api and was hoping someone here might be able to help me.
I have a jQuery method as follows ...
function OnInsert(evt) {
var truckId = $("#txtTruckId").val();
var truckReg = $("#txtTruckReg").val();
var description = $("#txtDescription").val();
var condition = $("#txtCondition").val();
var data = '{"obj":{"TruckId":"' + truckId + '","Reg":"' + truckReg +
'","Description":"' + description + '","Condition":"' + condition + '"}}';
var json = JSON.stringify(data)
$.ajax({
url: '/api/Values',
cache: false,
type: 'POST',
data: json,
dataType: 'json',
success: function (results) {
$("#txtTruckId").val('');
$("#txtTruckReg").val('');
$("#txtDescription").val('');
$("#txtCondition").val('');
$.getJSON("api/Values", LoadCustomers);
alert('Truck Added !');
}
})
}
When I debug that the 'data' variable successfully captures the data.
I then have a function in my WebApi controller ...
// POST api/values
public void Post(TruckInfo obj)
{
WebApiTestEntities db = new WebApiTestEntities();
db.TruckInfoes.Add(obj);
db.SaveChanges();
}
However, when I debug thst all of the parameters are showing a null value.
I found this:
http://kennytordeur.blogspot.co.uk/2012/12/web-api-passing-complex-type-in-json.html
Which states I need the following line of code in the Global.asax but that hasn't worked.
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
I also found this which kind of comes up with an answer but after trying to alter my code so it looks like the code they have written it still doesn't work.
jQuery posts null instead of JSON to ASP.NET Web API
Is any one able to help?
Thanks in advance
Lex
Start by fixing your JSON:
var data = {
truckId: truckId,
reg: truckReg,
description: description,
condition: condition
};
var json = JSON.stringify(data);
and then make sure you specify the correct content type request header:
$.ajax({
url: '/api/Values',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: json,
success: function (results) {
$("#txtTruckId").val('');
$("#txtTruckReg").val('');
$("#txtDescription").val('');
$("#txtCondition").val('');
$.getJSON("api/Values", LoadCustomers);
alert('Truck Added !');
}
});
I found this:
http://kennytordeur.blogspot.co.uk/2012/12/web-api-passing-complex-type-in-json.html
Which states I need the following line of code in the Global.asax but
that hasn't worked.
No, no, no. Not necessary as long as you format properly your JSON request, the Web API will bind it to your model.

Categories