How to access an array retrieved from controller via AJAX - c#

I call an MVC controller via Java and AJAX. The data goes to the controller, the controller returns a List. How do I access that list? This may seem trivial, but I can't find it anywhere on google or SO. Most of the examples I've found call for using:
...
success: function (r) {
var exemptions = r.d;
...
for (var i = 0; i < exemptions.length; i++){
ddlist.appent('<option>' + exemptions[i] + '</option>');
....
}
That method, however, results in this error:
Uncaught TypeError: Cannot read property 'length' of undefined
at Object.success (6:281)
at u (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)
at k (jquery.min.js:2)
at XMLHttpRequest.<anonymous> (jquery.min.js:2)
Controller Method:
public JsonResult GetValidRecords(int year)
{
var items = new List<SelectListItem>();
var Exemptions = model.Permits.Where(m => m.Year == year).OrderBy(m => m.Exemption).OrderBy(m => m.Year).ToList();
foreach (Permit x in Exemptions)
{
items.Insert(items.Count, new SelectListItem { Text = x.Exemption.ToString(), Value = x.Exemption.ToString() });
}
return Json(items, JsonRequestBehavior.AllowGet);
}
The dropdown box:
<text>EXEMPTION RENEWAL FORM</text>
<select id="dd" name="dd" onchange="CallRenewalReport(this.value)">
<option value="">Select Year First</option>
</select>
#Html.DropDownList("ddldate", new SelectList(Model.RYearList, "ID", "Year", "Select a year"), new { #onchange = "GetGoodRecords(this.value)", #AppendDataBoundItems = "False" })
break;
The JavaScript/AJAX query:
<script type="text/javascript">
function GetGoodRecords(val) {
alert(val);
var year = val;
var RootUrl = '#Url.Content("~/")';
$.ajax({
url: RootUrl + "Reports/GetValidRecords",
data: { year: year },
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var exemptions = response.d;
var ddlist = $('#dd');
ddlist.empty().append('<option selected="selected" value="0">Select Exemption</option>');
for (var i = 0; i < exemptions.length; i++) {
ddlist.append('<option>' + exemptions[i] + '</option>');
}
}
});
};
</script>
Can anyone spell this out to me in layman's terms?
Regards,
Carthax

Give this a shot in your success function:
success: function (response) {
for (var i = 0; i < response.length; i++) {
var obj = JSON.parse(JSON.stringify(response[i]));
alert(obj.Text);
}
}
This will show an alert of what is contained in each object of the response array.

(In case someone happens upon this question in google)
Based on input from #MikeMarshall, here is the solution that works:
The controller action is correct, but I'm putting it all in one place so you don't have to copy-and-paste from all over the page
public JsonResult GetValidRecords(int year)
{
var items = new List<SelectListItem>();
var Exemptions = model.Permits.Where(m => m.Year == year).OrderBy(m => m.Exemption).OrderBy(m => m.Year).ToList();
foreach (Permit x in Exemptions)
{
items.Insert(items.Count, new SelectListItem { Text = x.Exemption.ToString(), Value = x.Exemption.ToString() });
}
return Json(items, JsonRequestBehavior.AllowGet);
}
The razor code:
<text>EXEMPTION RENEWAL FORM</text>
<select id="dd" name="dd" onchange="CallRenewalReport(this.value)">
<option value="">Select Year First</option>
</select>
#Html.DropDownList("ddldate", new SelectList(Model.RYearList, "ID", "Year", "Select a year"), new { #onchange = "GetRecords(this.value)", #AppendDataBoundItems = "False" })
break;
The script:
<script type="text/javascript">
function GetRecords(val) {
alert(val);
var year = val;
var RootUrl = '#Url.Content("~/")';
$.ajax({
url: RootUrl + "Reports/GetValidRecords",
data: { year: year },
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
// get the dropdownlist
var ddlist = $('#dd');
// empty the dropdownlist and add "Select Exemption"
ddlist.empty().append('<option selected="selected" value="0">Select Exemption</option>');
// for each value in the response
for (var i = 0; i < response.length; i++) {
// properly query the Value and Text fields in the array
ddlist.append('<option value="' + response[i].Value + '">' + response[i].Text + '</option>');
}
}
});
};
</script>

Related

asp.net Razor Pages - Update select list based on the selection of another select list

I want to update a select list when the user selects a value in another select list. I've managed to get the first select list to call a get (or post) method on the model with a parameter, and can update the underlying data. But the second select list never shows the new values.
I'm not very experienced with asp.net, so what am I doing wrong?
Code below
.cshtml
<div>
<form method="post">
<select id="departureStation" asp-items="Model.DepartureStations" onchange="getDestinationStations()"></select>
<select id="destinationStation" asp-items="Model.DestinationStations"></select>
</form>
</div>
#section Scripts {
<script type="text/javascript">
function getDestinationStations() {
var selectedDepartureStationID = $("#departureStation").find(":selected").val();
console.log("selectedDepartureStationID = " + selectedDepartureStationID);
$.ajax({
type: "GET",
url: "/Index?handler=Departure",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: {
selectedDepartureStationID: selectedDepartureStationID
},
success: function(result) {
console.log("success - " + result);
},
error: function() {
console.log("failure");
}
})
}
</script>
}
.cs
public List<SelectListItem> DestinationStations
{
get
{
if (this._selectedDepartureStationID == -1)
return new List<SelectListItem>();
List<Models.Station> stations = new List<Models.Station>();
List<Models.RouteSegment> routeSegments = this._context.RouteSegments.Where(x => x.StationID == this._selectedDepartureStationID).ToList();
foreach (Models.RouteSegment routeSegment in routeSegments.DistinctBy(x => x.RouteID))
{
List<Models.RouteSegment> routeSegments2 = this._context.RouteSegments.Where(x => x.RouteID == routeSegment.RouteID).Include(x => x.Station).ToList();
stations.AddRange(routeSegments2.Select(x => x.Station));
}
return new List<SelectListItem>(stations.Distinct().ToList().Select(x => new SelectListItem { Value = x.StationID.ToString(), Text = x.StationName }).ToList());
}
}
public IndexModel(MyViewContext context)
{
this._context = context;
}
public void OnGet()
{
this.DepartureStations = this._context.Stations.Select(x => new SelectListItem { Value = x.StationID.ToString(), Text = x.StationName }).ToList();
}
public IActionResult OnGetDeparture(int selectedDepartureStationID)
{
this._selectedDepartureStationID = selectedDepartureStationID;
return Page();
}
Whenever your #departureStation select changes, your code will call getDestinationStations javascript code. Inside that function you are sending a request to your backend server to receive possible destination stations if I understood correctly. What you need to do here is when ajax request successes, add options dynamically based on your returned array or data.
I am assuming your "/Index?handler=Departure" returns a JSON like:
[
{
id: 1,
name: "station1"
},
{
id: 2,
name: "station2"
}
]
Check if code below works.
$.ajax({
type: "GET",
url: "/Index?handler=Departure",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: {
selectedDepartureStationID: selectedDepartureStationID
},
success: function(result) {
let destinationStationSelect = $('#destinationStationSelect');
let optionTemplate = $('<option></option>');
$.each(result, (index, element) => {
let option = optionTemplate.clone();
option.append(element.name);
option.attr('value', element.id);
destinationStationSelect.append(option);
});
},
error: function() {
console.log("failure");
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Displaying a list in a view from data passed from a controller

I'm passing a list in JSON format from my controller, the data from the list is not being displayed in the view for some reason.
Here is the data being passed in controller:
[HttpPost]
public ActionResult GetIndustryCat(string Country)
{ var dataContext = MvcApplication.GetDataContext();
var Location = dataContext.Locations.Single(c => c.Location_Name == Country);
var IndustryCat = dataContext.IndustryCategories.Where(c => c.Location_ID == Location.Location_ID).ToList();
return Json(new {Cat = IndustryCat.Select(c => c.IndustryCategory_Name) });
}
Here is the view:
</select>
<script>
$("#selectindustrycat").hide();
$("select")
.change(function () {
var str = "";
$("select option:selected").each(function () {
str += $(this).text() + " ";
});
$.ajax({
url: "GetIndustryCat",
type: "POST",
data: { Country: str },
success: function (data) {
}
}).done(function (data) {
for (var i = 0; i < data.length; i++) {
$("#selectindustrycat").append('<option value=' + i + '>' + i + '</option>');
}
$("#selectindustrycat").show();
});
});
</script>
The selection option list displays but it has no data in it.
You need change from data to data.Cat
for (var i = 0; i < data.Cat.length; i++) {
$("#selectindustrycat").append('<option value=' + i + '>' + i + '</option>');
}

Add multiple records setting properties using an index

I have a table full of checkboxes, and at the top there's a select all checkbox. Once clicked, I am making an ajax call that passes in a list of invoice_ids as well as the check_run_id of another table. What I'm having difficulty with is setting the property of an object based on the index of the list of invoices. The code will probably explain better. Thanks for any help.
public static void SaveInvoicesForPayment(List<int> invoiceIDs, int checkRunID)
{
using (MiniProfiler.Current.Step("SaveInvoices()"))
using (var context = rempscoDataContext.CreateContext())
{
toSave = invoiceIDs.Where(i => i > 0);
var toDelete = invoiceIDs.Where(i => i < 0).Select(i => -i);
toSave = toSave.Where(i => !toDelete.Contains(i));
var db_invoice_to_update = context.vendor_invoices.Where(si => toDelete.Contains(si.invoice_id));
var db_check_run_details_to_delete = context.check_run_details.Where(crd => crd.check_run_id == checkRunID);
db_invoice_to_update.ToList().ForEach(vi => { vi.check_run_id = null; });
db_check_run_details_to_delete.ToList().ForEach(crd => {
crd.bank_draft_id = null;
crd.is_active = false;
});
var invoice_to_save = context.vendor_invoices.Where(si => toSave.Contains(si.invoice_id)).ToList();
foreach (var crd in invoice_to_save)
{
context.check_run_details.InsertOnSubmit(new check_run_detail
{
invoice_id = crd.invoice_id,
check_run_id = checkRunID,
add_user = Security.CurrentUser,
add_date = DateTime.Now,
edit_user = Security.CurrentUser,
edit_date = DateTime.Now,
invoice_amount = **invoice_to_save[index??],**
is_active = true,
});
}
context.SubmitChanges();
}
}
Here's the ajax call as well just in case:
function doSaveInvoices($parent, checked) {
var $invoiceCheckBoxes = $parent.find('input.invoice[type="checkbox"]');
var checkRunID = $("#checkRunID").val();
var invoiceIDs = [];
if (checked) {
$invoiceCheckBoxes.each(function (i, c) {
var $checkbox = $(this);
invoiceIDs.push($checkbox.attr('invoice_id'));
$checkbox.attr('checked', true);
});
}
else {
$invoiceCheckBoxes.each(function (i, c) {
var $checkbox = $(this);
invoiceIDs.push(-$checkbox.attr('invoice_id'));
$checkbox.attr('checked', false);
});
}
var js = JSON.stringify({ invoiceIDs: invoiceIDs, checkRunID: checkRunID });
$.ajax({
url: './PayInvoicesWS.asmx/SaveInvoices',
data: js,
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
success: function (data) {
calculateTotal();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
sendErrorEmail(window.location.href, 'SaveInvoices', XMLHttpRequest);;
}
});

Internal server error in ajax post request

Guys I have problem with my ajax post request and it is not working for some dates i.e it does not hits controller but for some dates it works fine please help me to find out the bug
Here is my code
$("#getInfo").click(function ()
{
var elementValue = document.getElementById("tournamentID").value;
var startDateValue = document.getElementById("filterDateStartnew").value;
if (elementValue == null || elementValue == "" || startDateValue == null || startDateValue == "")
{
alert("please enter TournamentID and timestamp to get Info");
return false;
}
$.ajax({
type: "POST",
cache: false,
url: '/reports/gettournamentinfo',
data: { tournamentID: elementValue,date: startDateValue },
success: function (data)
{
var select = document.getElementById("TournamentLevel");
var length = select.options.length;
//Delete All Options
$('#TournamentLevel')
.find('option')
.remove()
.end()
var opt = document.createElement("option");
opt.text = "Any";
opt.value = -1;
document.getElementById("TournamentLevel").options.add(opt);
var count = data[0];
for (var i = 1; i <= count; i++)
{
var opt = document.createElement("option");
opt.text = i;
opt.value = i;
document.getElementById("TournamentLevel").options.add(opt);
}
for (var index = 1; index < data.length; ++index)
{
var opt = document.createElement("option");
opt.text = data[index];
opt.value = data[index];
document.getElementById("RunID").options.add(opt);
}
$("#SubmitForm").removeAttr('disabled');
},
error: function(data)
{
alert("there was no info for that tournamentID and that date");
$.unblockUI();
$('#TournamentLevel')
.find('option')
.remove()
.end()
return false;
}
});
return false;
});
Check for the data formats. For example if the client using dd/mm/yyyy and the server is expecting mm/dd/yyyy, you will see a HTTP 500 error as the model binder will fail to do the binding
Change your ajax post method like below.
$.ajax({ url: "/reports/gettournamentinfo", contentType: "application/json; charset=utf-8", type: "POST",
data: '{"tournamentID":"' + elementValue+ '", "date":"' + startDateValue + '"}',
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) { }
});

Two Listboxes with same value, I need to remove identicial value from one Listbox

I have two ASP ListBoxes. As you can see below, lbAvailable is populated on PageLoad with WebMethod and populates all cities. LbChoosen is populated depending on DropDown Value Chosen. The Dropdown has 4 options(ALL, Top25, Top50, Top100). for example if you choose Top 25 which is value 4, lbChosen populates top 25 cities (This all works).
MY PROBLEM IS lbAvaliable always populates all cities. So if i chose top 25 which populates top25 cities into lbChoosen, how can those value (top25 cities) be removed from lbAvailable
function LoadMarketsAvailableJS() {
var ddlFootprint = $('#ddlFootprint');
var lbChoosen = $('#lbChoosen');
var lbAvailable = $('#lbAvailable');
lbChoosen.empty();
var SelectedMarkets = [];
var url = "";
//Load lbAvailable on Page Load with all Markets
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Campaign.aspx/LoadAvailableMarkets",
dataType: "json",
success: function (msg) {
var obj = $.parseJSON(msg.d);
for (var i = 0; i < obj.Markets.length; i++) {
if (SelectedMarkets.indexOf(obj.Markets[i].id.toString()) == -1) {
$("#lbAvailable").append($("<option></option>")
.attr("value", obj.Markets[i].id)
.text(obj.Markets[i].name + " - " + obj.Markets[i].rank));
}
}
},
error: function(result) {
alert("Error");
}
});
//Check DropdownList
if (parseInt(ddlFootprint.val()) == 1) {
url = 'Campaign.aspx/LoadAvailableMarkets';
} else if (parseInt(ddlFootprint.val()) == 2) {
url = 'Campaign.aspx/LoadTop100Markets';
}
else if (parseInt(ddlFootprint.val()) == 3) {
url = 'Campaign.aspx/LoadTop50Markets';
}
else if (parseInt(ddlFootprint.val()) == 4) {
url = 'Campaign.aspx/LoadTop25Markets';
}
else if (parseInt(ddlFootprint.val()) == 5) {
url = 'Campaign.aspx/LoadAvailableMarkets';
}
//Load Select Dropdown Value to lbChoosen
if (url.length > 0) {
$.ajax({
type: "POST",
url: url,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var obj = $.parseJSON(msg.d);
for (var i = 0; i < obj.Markets.length; i++) {
if (SelectedMarkets.indexOf(obj.Markets[i].id.toString()) == -1) {
lbChoosen
.append($("<option></option>")
.attr("value", obj.Markets[i].id)
.text(obj.Markets[i].name + " - " + obj.Markets[i].rank));
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
},
complete: function (jqXHR, textStatus) {
}
});
}
}
Assuming I've understood what you're asking, if you want to remove options from lbAvailable as they're added to lbChoosen you should be add the following line:
lbAvailable.find('option[value="' + obj.Markets[i].id + '"]').remove();
So your code will look something like:
success: function (msg) {
var obj = $.parseJSON(msg.d);
for (var i = 0; i < obj.Markets.length; i++) {
if (SelectedMarkets.indexOf(obj.Markets[i].id.toString()) == -1) {
lbChoosen
.append($("<option></option>")
.attr("value", obj.Markets[i].id)
.text(obj.Markets[i].name + " - " + obj.Markets[i].rank));
lbAvailable.find('option[value="' + obj.Markets[i].id + '"]').remove();
}
}
},

Categories