Parameter to Web Service via Jquery Ajax Call - ajax

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) + "'}"

Related

Sending data to MVC Controller with AJAX

I am trying to send data with AJAX to MVC Controller method, but I don't know what am I doing wrong.
Here is the AJAX call
$.ajax({
type: 'POST',
url: invokingControllerActionUrl,
data: "it is just a simple string",
success: function (data) {
window.location.href = link;
}
});
And here is the controller method. It is invoked, but the parameter is always null.
public IActionResult OnPostTest([FromBody] string stringValue)
{
// stringValue is always null :(
}
Change you ajax call to this
$.ajax({
type: 'POST',
url: invokingControllerActionUrl, // Confirm the Path in this variable Otherwise use #Url.Action("OnPostTest", "InvokingController")
data: {stringValue: "it is just a simple string"},
success: function (data) {
window.location.href = link;
}
});
And remove the [FromBody]. ALso its better to define type post. Not necessary though
[HttpPost]
public IActionResult OnPostTest( string stringValue)
{
// stringValue is always null :(
}
Depending on what Content-Type you are sending from JS, you might need to encode your string properly, as a form-value
...
data: 'stringValue="it is just a simple string"',
...
or e.g. JSON:
...
data: '{stringValue: "it is just a simple string"}',
...
See also this discussion
I haven't found an easy way to pass a string of unformatted data via parameter, unfortunately. According to this answer, you can do the following:
public IActionResult OnPostTest()
{
Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string stringValue = new StreamReader(req).ReadToEnd();
...
// process your stringValue here
...
}

jQuery Ajax returns undefined result from asp.net core controller's POST action

Can't make friends out of my AJAX and MVC 6 controller.
This is how I define AJAX call for SetFormValues POST-action:
Index.cshtml
$.ajax({
type: "Post",
url: "Home/SetFormValues",
data: { Name: name, Phone: phone },
dataType: "json",
success: function (result) {
SuccessFunction(result)
},
error: function () {
alert("ALARM!");
},
async: false
})
I see that the controller works and executes SetFormValues action which is defined as the following:
HomeController.cs
[HttpPost]
public JsonResult SetFormValues(string Name, string Phone)
{
string NameErrorStr = string.IsNullOrWhiteSpace(Name) ? "Обязательное поле" : string.Empty;
string PhoneErrorStr = string.IsNullOrWhiteSpace(Phone) ? "Обязательное поле" : string.Empty;
var result = new { NameError = NameErrorStr, PhoneError = PhoneErrorStr };
var jresult = Json(result);
return jresult;
}
Debugger shows that action executes and my resulting JSON object fills correctly:
Finally, his is how SuccessFunction(result) is defined:
Index.cshtml again
function SuccessFunction(result) {
alert("Success function shit executed. result=" +
result + "NameError=" +
result.NameError + ". PhoneError=" +
result.PhoneError);
$("#nameerror").append(result.NameError);
$("#phoneerror").append(result.PhoneError);
}
Function works, alert is raised but result stay 'undefined' no matter what I do:
result = [object Object]
result.val = undefined
Maybe I have to deserialize JSON result properly or fill some properties in it's declaration above, I don't know.
I'm using the lattest libraries for jquery, validate and unobtrusive.
I also tried JSON.parse(result), as it mentioned in the lattest jQuery specification, but it didn't work as well.
Please, help me :)
In asp.net core, by default, the serializer uses camelCase property names for json serialization. So your result will be like this
{"nameError":"some message","phoneError":"some message here"}
Javascript is case sensitive. So use the correct case
$("#nameerror").append(result.nameError);
$("#phoneerror").append(result.phoneError);
For reference : MVC now serializes JSON with camel case names by default
its working perfectly when i have added this line in startup file
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddDbContext<DataContext>(option => option.UseSqlServer(Configuration.GetConnectionString("DbCrudOperation")));
}
function Edit(id) {
$.ajax({
type: 'GET',
url: "/AjacCrud/EditPahe/" + id,
dataType: 'JSON',
contentType: "application/json",
success: function (response) {
$("#nameEmp").val(response.ID);
console.log(response.ID);
},
error: function (GetError) {
alert(GetError.responseText);
}
});
};

How to pass complex JSON object in mvc action method?

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/

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