Can't send array from jQuery to MVC 4 controller - javascript

I've googled this up and checked all over StackOverflow but I must be missing something... I have unobtrusive jQuery that hijaks a simple button click. It counts up the checkboxes and adds each checked boxes value to an array. The list is correct when I use an alert box in jQuery but the array never makes it to the controller side. The code flows to the controller but I break on var resolutionViewModel=new ResolutionViewModel(); and check trans - the argument is null. I'm new to jQuery and could really use the help here.
jQuery
// Return the selected transactions
function resolveTransactions() {
$('#btnResolve').click(function() {
var selectedTransactions = new Array();
$('input[name="chkTransaction"]:checked').each(function() {
selectedTransactions.push(this.value);
});
if (selectedTransactions.length > 0) {
$.ajax({
type: 'POST',
dataType: 'json',
url: 'http://localhost/AuditLog/Home/ResolutionFormDisplay',
contentType: 'application/json; charset=utf-8',
data: {trans : selectedTransactions},
traditional: true,
success: function (data) { alert(data); },
error: function(xhr, status, errorThrown) { alert("Error: " + errorThrown); }
});
}
});
};
Controller side
[HttpPost]
public PartialViewResult ResolutionFormDisplay(List<string> trans)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}

Try having your controller accept a List, rather than just a single string (since you're not passing a single string):
[HttpPost]
public PartialViewResult ResolutionFormDisplay(List<string> value)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}

Posted JSON needs to have named properties matching parameters in your controller method. Check the 'network' tab in Chrome dev tools and see exactly what you're posting, it's probably something like this:
"{\"value\":\"...\"}"
There is no value property to pass to your controller method's value parameter. I think the best would be just to get rid of the `JSON.stringify" and accept a list like Colin's answer, but if you want to take it as a string, the JSON string needs to be the value property of an object, not the other way around:
data: {value : JSON.stringify(selectedTransactions)},

Try passing your array as follows:
data:"{'trans':" + JSON.stringify(selectedTransactions)+"}"
Your method should be as follows:
public void Method(List<string> trans)
{
//Your implementation
}

SOLUTION:
The $.ajax postback was not sending properly formatted data to the controller. I discovered this by using the network tab in IE and looking at the Request Body of the POSTed http. It looked like this:transaction_table_length=10&chkTransaction=22&chkTransaction=23 -- It should have looked like this: {"trans":["22","23"]}. To solve this issue I stringified the property name and array as shown below, changed the dataType to 'text', and made the parameter on the controller action method take a String[] trans.
jQuery
// Return the selected transactions
function resolveTransactions() {
$('#btnResolve').click(function() {
var selectedTransactions = new Array();
$('input[name="chkTransaction"]:checked').each(function() {
selectedTransactions.push(this.value);
});
if (selectedTransactions.length > 0) {
$.ajax({
type: 'POST',
dataType: 'text',
url: 'http://localhost/AuditLog/Home/ResolutionFormDisplay',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ trans:selectedTransactions }),
traditional: true,
success: function (data) { alert(data); },
error: function(xhr, status, errorThrown) { alert(" Error: " + errorThrown); }
});
} else {
alert('You must select (check) at least one transaction to apply a resolution.');
return false;
}
return false;
});
};
MVC 4 controller action
[HttpPost]
public PartialViewResult ResolutionFormDisplay(string[] trans)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}

Related

Returing a list of strings and iterating over it

I am new to jQuery and I am trying to iterate through a list of strings after making an ajax call to a controller. In this controller, I am returning a list of strings and I want to iterate over this list in jquery and present it to the screen. Here is my code.
This is my controller
[HttpPost]
public ActionResult GetComments() {
var cmts = ex.GetComments(psts, psons);
var lstCmt = ex.GetCommentsList(cments, psons);
return Json(lstCmt);
}
This is my view:
<div>
<button id="ldBtn" class="btn btn-primary">Load</button>
</div>
<div id="cments">
</div>
<script src="~/Scripts/jquery-3.2.1.js"></script>
<script>
$(document).ready(function() {
$("#ldBtn").on('click', function(evt) {
$("#cments").empty();
$.ajax({
type: "POST",
dataType: "html",
url: '#Url.Action("GetComments")',
data: {},
success: function(lists) {
//Something needs to be fixed here
$.each(lists, function(i, name) {
$('#comments').append('<p>' + name.Value + '</p>');
});
}
});
});
});
</script>
When I return the list, I am getting a huge string. How do I fix this?
Thanks in Advance
There's a couple of issues in your JS code. Firstly you're telling jQuery to expect a HTML response in the dataType setting. This is why you see the response as a string. This should be changed to JSON instead, that way jQuery will deserialise the response for you.
Secondly you're attempting to concatenate a Value property on each item in the list, yet they are strings (as you state you're returning a List<string> from your action), and will not have that property. You can simply append the name itself. Try this:
$("#ldBtn").on('click', function(evt) {
$("#cments").empty();
$.ajax({
url: '#Url.Action("GetComments")',
type: "POST",
dataType: 'json',
success: function(comments) {
$('#cments').append('<p>' + comments.join('</p><p>') + '</p>');
}
});
});
I assume the #comments/#cments discrepancy is only due to amending parts of your code when creating the question.
Also note that I simplified the append() logic so that it appends all comments in a single call, which should be slightly faster.

How to call a function in another MVC controller using AJAX in Jquery

My folder structure looks like this. Both of these folders are contained within the Area folder.
I am trying to call a function from the EmailController inside ITRequests/Scripts/Edit.js and it fails to find it.
The .js code look likes this
$(document).on('change', '#StatusId', function (event) {
event.preventDefault();
debugger;
if(( $('#OldStatus').val() ) != ( $('#StatusId').val()) ) //Aka if the user switched the status on submit
{
var status_description = [$('#OldStatus').val(), $('#StatusId').val()];
$.ajax({
url: "/Email/Email/statusChangeEmail",
type: 'POST',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ 'request': $('#RequestId').val(), 'status_descriptions': status_description }),
done: function (data) {
debugger;
alert("working");
}
})
}
})
RequestId is a hidden value on the page which is being picked up correctly, likewise the status_description field is taking the correct values and (tries to) pass them to the function.
The function EmailController.cs is defined as such
[HttpPost]
public ActionResult statusChangeEmail(int request, string[] status_descriptions)
{
//stuff happens
return Json(1);
}
However every time this happens I get this error message
Why your URL is /Email/Email/statusChangeEmail? It should be /Email/statusChangeEmail.
The /Email means EmailController and /statusChangeEmail means controller action statusChangeEmail .

Calling a HTTP POST method in a MVC Controller from the View's Javascript & Database saving

I am trying to update a value in my database. When the user presses the update button this script is called.
View Code:
<script>
function scr_UpdateQuote(field) {
var r = confirm("Are you sure you want to update your quote?");
if (r == true) {
var textBox_UserTitle = document.getElementById(field);
*CODE TO POST METHOD HERE*
}
}
</script>
In the controller, the value is then revived and saved into the database. A message is sent back to let the user know their quote was updated.
Controller Code:
[HttpGet]
public ActionResult UpdateQuote(string newQuote)
{
*REPLACE QUOTE IN DATABASE*
ViewBag.QuoteUpdated = "Your Quote has been updated.";
return View();
}
I am having difficulty finding out how to write the code described between the **'s
(For the database part I have a user-id that can be used to identify the row)
You can use form posting like this:
$("#YourForm").submit(function() {
$.post("/YourController/UpdateQuote", $("#YourForm").serialize())
//this will serialize your form into:
// newQuote=someValue&&someOtherVariable=someOtherValue etc.
.done(function(data) {
// do what ever you want with the server response
});
})
or you can use an ajax post:
$.ajax({
type: "POST",
url: "/YourController/UpdateQuote",
data: {newQuote: document.getElementById(field)},
dataType: "json",
success: function(data) {
// do what ever you want with the server response
},
error: function(){
// error handling
}
});
For using the data, assuming you have an DbContext called MyDbContext:
[HttpGet]
public ActionResult UpdateQuote(string newQuote)
{
// get userID somehow, either from session, or pass as another parameter here
using (var dc = new MyDbContext)
{
var quoteToUpdate = dc.QuotesTable.FirstOrDefault(q => q.UserID == userID)
quoteToUpdate.quoteColumn = newQuote;
dc.SaveChanges();
}
ViewBag.QuoteUpdated = "Your Quote has been updated.";
return View();
}

Change input name attributes after getting html data from action through AJAX in ASP.NET MVC

I have a simple ajax request which get from server a generated HTML, like:
$.ajax({
url: '/GetData'
type: "POST",
dataType: "html",
data: ...,
success: function(data) {
// here I want to change `name` attributes of inputs
// before print on page
// but it doesn't work, so, how to manage this ?
$(data).find("input[name='test']").prop("name", "anotherValue");
$("myDiv").prepend($(data));
}
});
and my action is simple:
[HttpPost]
public ActionResult GetData(){
return PartialView("myview", new MyModel());
}
I want to change input name attributes before print them in html page. If I do in success function (see above) then no change is made.
Why ? To to achieve this ?
try something like
$("input").each(function() {
if($(this).prop("name") == "test") $(this).prop("name", "anotherValue");
});
Data cannot be edited unless you append them to the DOM
So, use String.Replace function
var removed=data.replace("name='test'","anotherValue")
.replace('name="test"',"anotherValue");
$("myDiv").prepend(removed);
or do this
$(data).prependTo("myDiv").find("input[name='test']").prop("name", "anotherValue");

call controller action from .cshtml page with jquery

I am trying to call a controller action from a jquery UI dialog.
What I have currently is this:
.html("<p><textarea name=\"TextMessage\" id=\"textItems\" rows=\"10\" cols=\"72\" /><br /><br /><input type=\"button\" style=\"float:right;\" id=\"submitData\" onclick=\"Test()\" value=\"Submit\" /></p>");
The script I am using to call the controller action is this one:
<script type="text/javascript">
function Test() {
$ajax({
url: '<%= Url.Action("GetData", "Report") %>',
success: function (data) {
alert(data);
}
});
};
</script>
And the controller action is this:
[HttpGet]
public JsonResult GetData()
{
return Json("success", JsonRequestBehavior.AllowGet);
}
I would like to know if I am doing something wrong, I am trying to get this to work but without any success. When I am trying directly to start the controller via http://localhost:1322/Report/GetData it works fine, so that means that the script is not setup properly.
You should try:
url:'#Url.Action("GetData", "Report")'
MVC will automatically add "Controller" to the end of the second parameter when it is looking for the controller.
Edit:
This code may work:
function Test() {
$.ajax({
type: "GET",
dataType: "json",
url: '#Url.Action("GetData", "Report")',
contentType: "application/json; charset=utf-8",
success: function (data) {
alert(data);
},
error: function(xhr, status, error) {
alert(error);
}
});
}
Edit 2:
Changed to use Razor syntax so that this code will work with Razor/MVC3.
You are using MVC-2 syntax on Url.Action. This should work:
function Test() {
$.ajax(
{
url: '#Url.Action("GetData", "Report")',
dataType: 'json',
success: function (data) {
alert(data);
},
error: function (x, err, desc) {
alert(desc);
}
}
);
};
Because you are calling an action method that is returning a json object you can use the jQuery.getJSON() method.
<script type="text/javascript">
function Test() {
$.getJSON(
'#this.Url.Action("GetData", "Report")',
function (data) {
alert(data);
}
});
};
</script>
You may try jsaction too:
http://jsaction.codeplex.com
We can call Controller method using Javascript / Jquery very easily as follows:
Suppose following is the Controller method to be called returning an array of some class objects. Let the class is 'A'
public JsonResult SubMenu_Click(string param1, string param2)
{
A[] arr = null;
try
{
Processing...
Get Result and fill arr.
}
catch { }
return Json(arr , JsonRequestBehavior.AllowGet);
}
Following is the complex type (class)
public class A
{
public string property1 {get ; set ;}
public string property2 {get ; set ;}
}
Now it was turn to call above controller method by JQUERY. Following is the Jquery function to call the controller method.
function callControllerMethod(value1 , value2) {
var strMethodUrl = '#Url.Action("SubMenu_Click", "Home")?param1=value1 &param2=value2'
$.getJSON(strMethodUrl, receieveResponse);
}
function receieveResponse(response) {
if (response != null) {
for (var i = 0; i < response.length; i++) {
alert(response[i].property1);
}
}
}
In the above Jquery function 'callControllerMethod' we develop controller method url and put that in a variable named 'strMehodUrl' and call getJSON method of Jquery API.
receieveResponse is the callback function receiving the response or return value of the controllers method.
Here we made use of JSON , since we can't make use of the C# class object
directly into the javascript function , so we converted the result (arr) in controller method into JSON object as follows:
Json(arr , JsonRequestBehavior.AllowGet);
and returned that Json object.
Now in callback function of the Javascript / JQuery we can make use of this resultant JSON object and work accordingly to show response data on UI.
For more detail click here

Categories

Resources