Trouble posting form data to MVC4 controller action method using jQuery - c#

I have a form with a textarea and when trying to send the information, I am using JSON.stringify, I get errors. Here is the code:
$.ajax({
type: "POST",
dataType: "json",
data: JSON.stringify({
reportid: data["reportid"], //Guid
assessmentId: data["assessmentId"], //Guid
title: data["title"], //string
body: data["body"], //string
section: data["section"], //string
reportsection: data["reportSection"] //string
}),
url: "/Assessments/ModifyAssessmentTemplateText",
success: function (data) {
lastModified = data["LastModified"];
updateLastModified(lastModified);
alert(data);
}
});
My controller method was set up as follows:
[POST("ModifyAssessmentTemplateText")]
[AjaxOnly]
public JsonResult ModifyAssessmentTemplateText(Guid reportid, Guid assessmentid, string title, string body, string section, string reportSection)
{
//...
}
I get a 500 server error.
I know that when I tried testing, and had only one parameter, reportid, and had my method accept a string, it worked. But when I set it to Guid I get the 500 error. Is there a way I should be parsing the JSON server side?
EDIT:
Note: when I don't use data, and I do
url: "/Assessments/ModifyAssessmentTemplateText?reportid=" + reportid
it works with no problem.

I think the answers so far are dancing around the point. Your data doesn't have to be a string at all, have you tried this?
$.ajax({
type: "POST",
dataType: "json",
data: {
reportid: data["reportid"], //Guid
assessmentId: data["assessmentId"], //Guid
title: data["title"], //string
body: data["body"], //string
section: data["section"], //string
reportsection: data["reportSection"] //string
},
url: "/Assessments/ModifyAssessmentTemplateText",
success: function (data) {
lastModified = data["LastModified"];
updateLastModified(lastModified);
alert(data);
}
});

You don't have to call JSON.stringify, because you are expecting parameters so it should be key value pairs and you are trying to POST JSON object.
You may crate parameter that matches JavaScript object and then use JSON.stringify, this way model binder will try to deserialize it into the object.

So I managed to find the answer on http://encosia.com/asmx-scriptservice-mistake-invalid-json-primitive/. Essentially, what I needed to do was encapsulate the JSON string in quotation marks. This made the string a JSON string rather than a JavaScript Object literal.
Quoted from the site:
The solution is as simple as two single-quotes:
// RIGHT
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'WebService.asmx/Hello',
data: '{ FirstName: "Dave", LastName: "Ward" }'
});
Did you spot the difference?
Instead of a JavaScript object literal, the data parameter is a JSON string now.
The difference is subtle, but helpful to understand. Since it’s a string,
jQuery won’t attempt to perform any further transformation,
and the JSON string will be unimpeded as it is passed to the ASMX ScriptService.

Have you tried posting the guid as a string and parsing out a Guid on the server?

If you trying to send data as json. You should know:
Specifying the Data Type for AJAX Requests
json - Evaluates the response as JSON and sends a JavaScript Object to the success callback.
But how binder detect that it is json request?
By contentType: 'application/json; charset=utf-8'

Related

ASP.NET MVC JSON get value with two Parameters

I am trying to get value based on 2 parameters, below is my function where I added my 2 parameters in JSON stringify :
function GetItemLocationOnHand(itemId, locationId) {
var data = JSON.stringify({
itemId: itemId,
locationId: locationId
});
$.ajax({
async: true,
type: 'GET',
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
data: data,
url: 'getItemInventory3',
success: function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
},
error: function () {
alert("Error")
}
});
}
Below is my code in my controller to retrieve the data I want based on these two parameters :
[HttpGet]
public JsonResult GetItemLocationOnHand(int itemId, int locationId)
{
var itemLocQuantity = objDB.ItemLocationDatas.Single(items => items.ItemId == itemId && items.LocationId == locationId).Quantity;
return Json(itemLocQuantity, JsonRequestBehavior.AllowGet);
}
Upon calling this function via below on change code, I can't seem to get my data and is always returning the error.. If I only have 1 parameter, then no error encountered.
Please advise what went wrong when trying to pass 2 parameters.
$("#LocationId").change(function () {
var itemId = $("#ItemId").val();
var locationId = $("#LocationId").val();
GetItemLocationOnHand(itemId, locationId)
});
Issue solved by doing the following :
added correct URL which is GetItemLocationOnHand
removed Stringify and used var data = ({ itemId: itemId, locationId:
locationId });
thanks a lot to Freedom and Reflective and others for your comments!
function GetItemLocationOnHand(itemId, locationId) {
var data = ({ itemId: itemId, locationId: locationId });
$.ajax({
async: true,
type: 'GET',
dataType: 'JSON',
contentType: 'application/json; charset=utf-8',
data: data,
url: 'getItemLocationOnHand',
success: function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
},
error: function () {
alert("Error")
}
});
}
Just to avoid some misunderstanding how AJAX GET works and setting some parameters which you don't have to set (i.e. you are still not so deep into jQuery AJAX) you may use the shortcut they also implemented i.e. $.get so your request will look as simple as that and you can't get wrong as it will use the proper defaults for GET. If you want the response to be treated as JSON, just set Content-type of your response headers (from backed) to application/json. This will be checked by jQuery AJAX response handler and it will parse the incoming data as JSON.
var data = {itemId: 1, locationId: 2 };
$.get('GetItemLocationOnHand', data, function (data) {
$("#txtInventory3").val(parseFloat(data).toFixed(2));
}).fail(function (jqXHR, textStatus ) {
alert(`Error = ${jqXHR.status} ${textStatus}`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
See my example below. This works for me when doing ajax requests to a MVC controller with multiple params.
Below is my MVC controller action with multiple params.
// GET
[HttpGet]
public ActionResult Index(string referenceID, int typeID, int supplierID, bool isArchived)
{
// Do CODE here
}
Below is my Ajax request that I use to get or post. Depending on your needs. I use data type 'JSON' and format my data as a JSON object.
var formData = {referenceID: 'Test', typeID: 3, supplierID: 2, isArchived: false};
$.ajax({
type: 'GET',
cache: false,
url: getActionUrl, // url: domain/controller/action |or| domain/area/controller/action
dataType: 'json',
contentType: 'application/json; charset=utf-8',
headers: headers, // ignore if not needed. I use it for __RequestVerificationToken
data: formData,
success: function (data, status, xml) {
// do something with the data
},
error: function (xml, status, error) {
console.log(xml)
// do something if there was an error
},
complete: function (xml, status) {
}
});
I think your issue might be that you are using 'JSON.stringify'. It could be interpreting your JSON string as a single parameter input and not two separate parameters.
Please see below snippets from documentation. https://api.jquery.com/jquery.ajax/
If json is specified, the response is parsed using jQuery.parseJSON before being passed, as an object, to the success handler. The parsed JSON object is made available through the responseJSON property of the jqXHR object.
The data option can contain either a query string of the form key1=value1&key2=value2, or an object of the form {key1: 'value1', key2: 'value2'}. If the latter form is used, the data is converted into a query string using jQuery.param() before it is sent. This processing can be circumvented by setting processData to false. The processing might be undesirable if you wish to send an XML object to the server; in this case, change the contentType option from application/x-www-form-urlencoded to a more appropriate MIME type.

Can't get ISO-8601 JSON DateTime to properly send in GET

I have a KnockoutJS viewmodel I'm working with, and sending a JSON date as a parameter in a GET request to WebAPI apparently is difficult.
I've got the following happening to my request
var params = {
userId: currentUser,
startRange: ko.toJSON(self.selectedDate()),
endRange: ko.toJSON(self.selectedDate())
}
$.ajax({
type: "GET",
contentType: 'application/json; charset=utf-8',
cache: false,
dataType: 'json',
url: url,
data: params,
beforeSend: function (xhr, settings) {
sf.setModuleHeaders(xhr);
}
}).done(function(data) {
}).fail(function () {
}).always(function() {
});
On my WebAPI controller, the Start and End dates keep coming up null
public HttpResponseMessage GetViolationsInRange(int userId, DateTime? startRange, DateTime? endRange)
Inspecting the request, this is what it outputs
/API/Cert/GetViolationsInRange?userId=20&startRange=%222015-09-01T04%3A00%3A00.000Z%22&endRange=%222015-09-01T04%3A00%3A00.000Z%22
Any ideas why this is occurring and why I keep getting tripped up by this?
EDIT: It seems that by not using jQuery's AJAX 'data' parameter, and just appending the values to the URL, it doesn't escape the JSON representations. Is there a clean way to do what jQuery does adding GET parameters without manually appending them?
try removing the use of ko.toJSON().
The date will be a property of your params object.
Jquery with dataType : 'json' will translate the date object properly.

Asp.net MVC 5 Modelbinding multiple JSON objects (knockoutjs)

Ok. I've encountered a problem that i just can't understand.
First of all, i'm trying to post several ko.observableArrays to the controller as JSON and modelbinding them seperately. When i post only one and don't name it in the data attribute of .ajax it posts just fine and modelbinds flawlessly.
This is my a snippet from my viewModel and is how i am attempting to post the two JSON objects.
self.timeRanges = ko.observableArray();
self.geoRequirements = ko.observableArray();
self.saveWorkWish = function() {
$.ajax({
url: "#Url.Action("SaveWorkWish")",
type: "POST",
contentType: 'application/json; charset=utf-8',
data: {
timeRanges: ko.toJSON(self.timeRanges()),
geoRequirements: ko.toJSON(self.geoRequirements())
},
complete: function (data) {
console.log(data);
}
});
};
My Action
public JsonResult SaveWorkWish(IList<JSONTimeRanges> timeRanges, IList<JSONGeoRequirements> geoRequirements)
{
// do stuff
}
I get this exception:
Invalid JSON primitive: timeRanges.
Interesting to note is that, when i do:
$.ajax({
url: "#Url.Action("SaveWorkWish")",
type: "POST",
contentType: 'application/json; charset=utf-8',
data: ko.toJSON(self.timeRanges()),
complete: function (data) {
console.log(data);
}
});
And
public JsonResult SaveWorkWish(IList<JSONTimeRanges> timeRanges)
{
// do stuff
}
It works just fine.
Lastly a thing that i noticed, and is likely the cause of the error is that:
When i post 2 Jsons like in the example,
this is what chrome tells me i post:
timeRanges=%5B%7B%22startDate%22%3A%2214-09-2014%22%2C%22endDate%22%3A%2220-09-2014%22%2C.....etc..
and in the working example:
it is a well formated and readable JSON object.
So it seems like the error is indeed correct and that i am not sending valid JSON to the controller.
But..what am i doing wrong?
Try to convert observables to JSON first and then convert the whole object to json string:
data: JSON.stringify({
timeRanges: ko.toJS(self.timeRanges()),
geoRequirements: ko.toJS(self.geoRequirements())
}),

MVC Send list through AJAX

Okay, I've seen tons of questions posted regarding this question, but none of the answers has actually worked for me, here's my AJAX:
$.ajax({
url: "/FilterSessions/GetFilterSession",
type: "GET",
dataType: "json",
data: jsonFilters,
traditional: true,
success: function (response) {
//Haha, it's never entering here. not really.
}
});
var "jsonFilters" contains an array with the following data:
[0] = { Path: "Test", Name: "More testing", Value: "Test Value" },
[1] = { Path: "Test", Name: "More testing", Value: "Test Value" }
And this is my controller:
public ActionResult GetFilterSession(List<FilterSessionModel> jsonFilters)
{
//Do things
return Json(false, JsonRequestBehavior.AllowGet);
}
jsonFilters always remains null... I have also tried adding contentType: "application/json; charset=utf-8" to the AJAX call... but that didn't really do anything
Finally, the class FilterSessionModel is structured as follows:
public class FilterSessionModel
{
public string Path { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
Any ideas as to what I might be missing or what might be happening?
Things I've tried so far:
Setting "traditional: true", setting "contentType", using JSON.stringify and attempting to accept a string in the MVC Controller (no-go)
UPDATE: Thanks to the answer below I realized that what was missing was to send over the data with the param Id like so:
data: "{param1ID:"+ param1Val+"}"
I would try switching out the type on your action.
List<FilterSessionModel>
Pretty sure the above is not going to work, I would try something like Object.
Or possibly a string that I would then use newton json dll to push into your List of Class.
The problem boils down to your action being unable to figure out the type, assuming you are checking your data prior to the ajax get being called.
**Update due to more info. Add in the error portion and view those vars on return from your controller, also fire up fiddler and watch what your are getting for http numbers.
$.ajax({
type: "POST",
url: "Servicename.asmx/DoSomeCalculation",
data: "{param1ID:"+ param1Val+"}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
UseReturnedData(msg.d);
},
error: function(x, t, m, b) {
//Look at the vars above to see what is in them.
}
});
I think what you are looking for is answered here:
Passing A List Of Objects Into An MVC Controller Method Using jQuery Ajax
First off I'm making the assumption that your $.ajax is for JQuery and not some other Javascript framework. Please correct me if that's wrong.
ASP.NET MVC can actually do what you are asking it to (resolve data sent via AJAX to a List<FilterSessionModel>, but it seems to have a difficult time doing it via a GET request. It would help to know which version of ASP.NET MVC you are using, as more is required to get this working on the older versions. However, what I'm suggesting should work on MVC 3 or 4.
When you send AJAX via JQuery using a GET request and passing it a JavaScript array, this is what you are sending to the server:
http://localhost:50195/FilterSessions/GetFilterSession?undefined=&undefined=
It's no wonder the model is null because no data is actually being sent.
I believe ASP.NET can accept objects (and even arrays of objects) like this, but it won't do so with it formatted as JSON (like via JSON.stringify) as that just results in the following request:
http://localhost:50195/FilterSessions/GetFilterSession?[{%22Path%22:%22Test%22,%22Name%22:%22TestName%22,%22Value%22:%22Testing%22},{%22Path%22:%22Test%22,%22Name%22:%22TestName%22,%22Value%22:%22Testing%22}]
The way you probably want to do this is with a POST request. ASP.NET MVC will actually accept a JSON string as POST data and will decode it and resolve the model properly. Your AJAX code works fine with a couple modifications:
$.ajax({
url: "/FilterSessions/GetFilterSession",
type: "POST", //Changed to POST
dataType: "json",
data: JSON.stringify(jsonFilters), //Pack data in a JSON package.
contentType: "application/json; charset=utf-8", //Added so ASP recognized JSON
traditional: true,
success: function (response) {
alert('Success!');
}
});
The controller you posted should recognize POST data already, but in case it doesn't, a simple [HttpPost] attribute is all you need:
[HttpPost]
public ActionResult GetFilterSession(List<FilterSessionModel> jsonFilters)
{
//Do things
return Json(false, JsonRequestBehavior.AllowGet);
}
javascript or ajax call never type cast the object. . .you need to set type of the controller side parameter either string or List else you can also set the Object type. . If you modified codein that way.. .Your code definitely work !!!
$.ajax({
url: "/FilterSessions/GetFilterSession",
type: "GET",
dataType: "json",
data:JSON.stringify({ 'jsonFilters': jsonFilters}),
contentType: 'application/json; charset=utf-8',
success: function (response) {
//Do your action
}
});

How do I build a JSON object to send to an AJAX WebService?

After trying to format my JSON data by hand in javascript and failing miserably, I realized there's probably a better way. Here's what the code for the web service method and relevant classes looks like in C#:
[WebMethod]
public Response ValidateAddress(Request request)
{
return new test_AddressValidation().GenerateResponse(
test_AddressValidation.ResponseType.Ambiguous);
}
...
public class Request
{
public Address Address;
}
public class Address
{
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
public AddressClassification AddressClassification;
}
public class AddressClassification
{
public int Code;
public string Description;
}
The web service works great with using SOAP/XML, but I can't seem to get a valid response using javascript and jQuery because the message I get back from the server has a problem with my hand-coded JSON.
I can't use the jQuery getJSON function because the request requires HTTP POST, so I'm using the lower-level ajax function instead:
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
data: "{\"Address\":{\"Address1\":\"123 Main Street\",\"Address2\":null,\"City\":\"New York\",\"State\":\"NY\",\"Zip\":\"10000\",\"AddressClassification\":null}}",
dataType: "json",
success: function(response){
alert(response);
}
})
The ajax function is submitting everything specified in data:, which is where my problem is. How do I build a properly formatted JSON object in javascript so I can plug it in to my ajax call like so:
data: theRequest
I'll eventually be pulling data out of text inputs in forms, but for now hard-coded test data is fine.
How do I build a properly formatted JSON object to send to the web service?
UPDATE: It turns out that the problem with my request wasn't the formatting of the JSON, as T.J. pointed out, but rather that my JSON text didn't conform to requirements of the web service. Here's a valid JSON request based on the code in the WebMethod:
'{"request":{"Address":{"Address1":"123 Main Street","Address2":"suite 20","City":"New York","State":"NY","Zip":"10000","AddressClassification":null}}}'
This brought up another question: When is case sensitivity important in JSON requests to ASP.NET web services (ASMX)?
The answer is very easy and based on my previous posts Can I return JSON from an .asmx Web Service if the ContentType is not JSON? and JQuery ajax call to httpget webmethod (c#) not working.
The data should be JSON-encoded. You should separate encode every input parameter. Because you have only one parameter you should do like following:
first construct you data as native JavaScript data like:
var myData = {Address: {Address1:"address data 1",
Address2:"address data 2",
City: "Bonn",
State: "NRW",
Zip: "53353",
{Code: 123,
Description: "bla bla"}}};
then give as a parameter of ajax request {request:$.toJSON(myData)}
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
data: {request:$.toJSON(myData)},
dataType: "json",
success: function(response){
alert(response);
}
})
instead of $.toJSON which come from the JSON plugin you can use another version (JSON.stringify) from http://www.json.org/
If your WebMethod had parameters like
public Response ValidateAddress(Request request1, Request myRequest2)
the value of data parameter of the ajax call should be like
data: {request1:$.toJSON(myData1), myRequest2:$.toJSON(myData2)}
or
data: {request1:JSON.stringify(myData1), myRequest2:JSON.stringify(myData2)}
if you prefer another version of JSON encoder.
Your problem breaks down into two parts:
Creating the JSON string
Your JSON in your quoted code is perfectly valid. But being hand-crafted is a pain. As others have called out, the easiest way to do this is to create a Javascript object and then JSON.stringify it. Example:
var data = {
"Address": {
"Address1": "123 Main Street",
"Address2": null,
"City": "New York",
"State": "NY",
"Zip": "10000",
"AddressClassification": null
}
};
data = JSON.stringify(data);
The first step above creates an object using Javascript object literal notation, which is a superset of JSON (as used above, it actually is the same as JSON, but ignore that). The second bit takes that object and converts it to a string.
Of course, the values above are literal strings, which is unlikely. Here's what it would look like if you had each of those values in a variable:
var data = {
"Address": {
"Address1": address1,
"Address2": address2,
"City": city,
"State": state,
"Zip": zip,
"AddressClassification": null
}
};
data = JSON.stringify(data);
Either way, now you have the string.
Sending the JSON string to the web service
You need to find out is whether the web service is expecting the JSON-formatted data to be the POST body, or if it's expecting the JSON data to be the value of a parameter in the more common name=value URL-encoded POST data. I would tend to expect the former, because the web service seems specifically designed to work with JSON-formatted data.
If it's supposed to be the POST body, well, I've never done that with jQuery, and what you have quoted looks correct to me reading the docs. If it's not working, I'd double-check that your object structure is really what they're expecting to see. For instance, if it's just validating a single address, I wonder if it's expecting to receive just an Address object, rather than an object containing an Address object, e.g.:
{
"Address1": "123 Main Street",
"Address2": null,
"City": "New York",
"State": "NY",
"Zip": "10000",
"AddressClassification": null
}
If it's supposed to be the value of a parameter in boring old URL-encoded multipart form data, then:
$.ajax({
type: "POST",
url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
data: "paramname=" + encodeURIComponent(data),
dataType: "json",
success: function(response){
alert(response);
}
})
I've removed the contentType so jQuery will fall back to its default ("application/x-www-form-urlencoded") and ensured the string we created above is properly encoded in that content type. You'll need to find out the paramname to use (perhaps "Address" and see my earlier comment about sending just the address, rather than an object containing an address child object?).
JSON.stringify will take a javascript object and turn it into a string. I bet though that if you create a Javascript object like
var jsonData = {
address: 'address',
address1: 'address1',
address2: 'address2'
};
and then pass in jsonData as 'data' in the ajax call, then it will convert the object to json text for you.
I would create a javascript object and then call JSON.stringify to turn it into valid JSON. You can download it from here.
You could do something like this:
var address= {};
address["Address1"] = "your val";
address["Address2"] = "your val";
address["City"] = "your val";
address["State"] = "your val";
address["Zip"] = "your val";
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
data: JSON.stringify(address),
dataType: "json",
success: function(response){
alert(response);
}
});
You need to pass it like this:
$.ajax({
type: "POST",
url: "WebService.asmx/WebMethodName",
data: "{'fname':'dave', 'lname':'ward'}",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
Have a look at this article for more details: 3 mistakes to avoid when using jQuery with ASP.NET AJAX
All apologies if this answer comes too late, or is a duplication.
From what I understand, it appears as though you're trying to send just the string of a JSON object. Try building an object and then working with its properties and sending it in as it is.
Example:
address = new Object();
address.Address = new Object();
address.Address.Address1 = "123 Main Street";
address.Address.Address2 = "";
address.Address.City = "New York";
address.Address.State = "NY";
address.Address.Zip = "10000";
address.Address.AddressClassification = null;
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://bmccorm-xp/HBUpsAddressValidation/AddressValidation.asmx/ValidateAddress",
data: address,
dataType: "json",
success: function(response){
alert(response);
}
});
Get yourself a jquery plugin that can convert any javascript object to json. For example:
http://plugins.jquery.com/project/json

Categories