Change TextBox Value and Update On Ajax Call - c#

I am working on an ecommerce site where I am stuck on the cart management. Basically before login, products are kept in a session and I am trying to update the product quantity stored in the session using Ajax. I mean whenever I write in the 'Quantity To Change', the changed value should be reflected in the 'Quantity' column.
Note: I've shortened the post and figured out why it wasn't firing while debugging. Actually I was unable to get the id of the associated product. Now it passes the id. That's it. Now I've another issue - The TextBox are being created dynamically with a for loop. I used developer tools to figure out how the TextBoxes are generated dynamically and it is something like this:
For Product 1: cartDetails_0__Quantity
For Product 2: cartDetails_1__Quantity
I am wondering how to grab the quantity or values from the dynamically generated TextBoxes. If I put the generated id from HTML directly to Ajax, then it updates the quantity. Otherwise it doesn't. I've tried to use a loop in Ajax but I think, I am getting it wrong. Please see the View.
The view:
<table border="1" width="100%" cellpadding="4">
<thead>
<tr>
<th style="text-align:center;">Name</th>
<th style="text-align:center;">Price</th>
<th style="text-align:center;">Quantity</th>
<th style="text-align:center;">Quantity To Change</th>
</tr>
</thead>
<tbody>
#if (ViewBag.CartDetails != null)
{
for (int i = 0; i < cartDetails.Count(); i++)
{
<tr>
<td style="text-align: center; display:none;">#Html.DisplayFor(model => cartDetails[i].ProductId)</td>
<td id="ID" style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].ProductName)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Price)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Quantity, new { #class = "quantityUpdate" })</td>
<td style="text-align: center;">#Html.TextBoxFor(model => cartDetails[i].Quantity, new { #class = "quantity", data_id = cartDetails[i].ProductId } )</td>
</tr>
}
}
</tbody>
</table>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
var url = '#Url.Action("UpdateCart")';
$(".quantityUpdate").change(function () {
var id = $(this).data('id');
var i = 0;
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, Quantity: $("#cartDetails_"+i+"__Quantity").val() }, function (response) {
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
alert(id);
alert($("#cartDetails_"+i+"__Quantity").val());
});
Here is an image sample that I am trying:

$('.quantity').change(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});
Instant Change
$('.quantity').keyup(function(){
$('.quantityUpdate').val($('.quantity').val());
// put code here
});

If the idea is to call ajax when you change the value in .quality textbox then this is how you should do:
$('.quantity').change(function(){
//your ajax call
});

Related

Update table in foreach loop with filtered model with Ajax (asp.net mvc c#)

I've developed an asp.net MVC web app where I have a table that shows some items in a model.
I can filter it now with a dropdown list using ajax
The model that i pass to the table is correct (if i go to the model before the foreach there are 3 rows instead of 10 thanks to the filter)
The problem is that the table doesn't change, it always shows all the rows as the initial request.
It look like it works but the table won't update...
There's my jquery ajax call:
$("#Dropdown1Id").on('change', function () {
//console.log("onchange");
//console.log($("#Dropdown1Id").val());
var drpdown1 = $("#Dropdown1Id").val();
var submit = $("#submitButton");
$.ajax({ // crea una chiamata AJAX
data: { data: drpdown1 }, // prendi i dati del form in questo caso del primo dropdown
type: "GET", // GET o POST
url: "/Select/Filter", // li passa al controller
success: function () { // se va con successo esegue il codice seguente
submit.click();
$("#frmId").submit();
},
error: function (error) {
console.log("error")
}
});
});
There's my controller action:
public ActionResult Filter(string data)
{
List<Card> cards = new List<Card>();
ViewBag.stato = new SelectList(myApi.GetState(), "Name", "Name");
if (data != null && data != "")
{
foreach (var card in model)
{
if (card.IdList == data || data == "")
cards.Add(card);
}
return View(cards);
}
return View(model);
}
There's my view with the daple and the dropdown:
#using (Html.BeginForm(new { id = "frmId"}))
{
#Html.AntiForgeryToken()
<table id="tb2">
<tr>
<th>
<h4> LIST : #Html.DropDownList("stato", null, new { #id = "Dropdown1Id" })</h4>
</th>
#*<th>
<h4>ARCHVIED : #Html.DropDownList("closed", null, new { #id = "Dropdown2Id" })</h4>
</th>*#
<th>
<input type="submit" value="Filter" class="btn btn-info" id="submitButton" />
</th>
</tr>
</table>
<br />
<div id="risultato"></div>
<table class="table" id="tb1">
<tr>
<th style="text-align:center">
TRELLO'S CARDS LIST
</th>
<th>LIST</th>
<th>ARCHVIED</th>
<th>Expiration date</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.IdList)
</td>
#if (item.Closed == "True")
{
<td>YES</td>
}
else
{
<td>NO</td>
}
#if (item.Due != null)
{
<td>
#Html.DisplayFor(modelItem => item.Due)
</td>
}
else
{
<td>
Not Present
</td>
}
</tr>
idList.Add(item.Id);
}
</table>
Let me get you through the execution stack and you'll understand why:
Your MVC view is loaded. When the view is returned to the frontend it is already in Html format. Check Server side rendering here
Basically it means that #foreach (var item in Model) will only execute on the server side and will not re-run when you hit an ajax call. This will only happen on a full post.
While in your page you fire up change dropdown event and the following happens:
An ajax call hit your controller
Data are being returned to the success function
Your success: function () is being executed.
A new form post occurs. See that you didn't do anything with the return data that was returned in the success: function(). You just posted back to the controller
After the post, the full view has returned ignoring any changes in the dropdown and in the data returned.
There are 2 solutions for your problem:
Do a full post and return a new view with the proper data
Write some more javascript to change the DOM inside your sucess function

the server responded with a status of 500 (Internal Server Error) in AngularJS

Js:
$scope.GetLocationList = function () {
var url = "/MasterSvc.asmx/GetAllLocationList";
var data = {};
var options = {};
$http.post(url, data, options).then(function (response) {
var dbfsr = response.data.d;
var LocData = {};
$scope.LocData = dbfsr;
}).catch(
function (response) {
console.log('return code: ' + response.status);
});
};
This is the JS function which is call on initController() on page load.
HTML:
<table class="table table-bordered table-hover"
style="width: 95%;font-size:12px" id="EmpTbl">
<tr>
<th>Location Code</th>
<th>Location Type</th>
<th>Location Name</th>
<th>Location Address</th>
<th>Contact Person</th>
<th>Contact No</th>
<th>Actions</th>
</tr>
<tr dir-paginate="loc in LocData|orderBy:sortKey:reverse|filter:search|itemsPerPage:10">
<td>{{loc.LocationCode}}</td>
<td>{{loc.LocationType}}</td>
<td>{{loc.LocationName}}</td>
<td>{{loc.LocationAddress}}</td>
<td>{{loc.ContactPerson}}</td>
<td>{{loc.ContactNo}}</td>
<td style="text-align: center">
<input type="button" class="btn btn-warning SelectLocation"
data-ng-click="GetLocationDetails(loc.LocationCode)"
value="View/Edit" id="SelectLocation" data-toggle="modal"
data-target="#myModal" />
</td>
</tr>
</table>
This is HTML code where paginate is use like ng-repeat and also use for pagination.
I am trying to bind the table using webService from Mysql database.It working fine when database select records are limit up to 240, But if record are more than 240 it showing me Internal server error 500. How to solve this. Please find the screen and code. Thanks.
You need to increase the max Size in the configuration
add this code in web.config backend
<httpRuntime maxRequestLength="52428800" executionTimeout="36000" />

Why is my REST method not being called by this jQuery?

I have a similar question about jQuery button click handler code not being fired at all here.
In this case, it is being fired (when the jQuery is added to a static page (Index.cshtml)), but my REST method is still not being reached. The console message explaining why is:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /LandingPage/GetQuadrantData
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1055.0
This is the jQuery, which indeed gets fired when the button is clicked, but the REST call is not being made:
<script>
$(function () {
var btnGetData = document.getElementById('btnGetData');
btnGetData.addEventListener("click", function () {
alert("It works");
var unitval = 'ABUELOS';
var begdateval = '2016-08-07';
var enddateval = '2016-08-13';
$.ajax({
type: 'GET',
url: '#Url.Action("GetQuadrantData", "LandingPage")',
data: { unit: unitval, begdate: begdateval, enddate: enddateval },
contentType: 'application/json',
cache: false,
success: function (returneddata) {
},
error: function () {
alert('hey, boo-boo!');
}
});
});
});
</script>
The REST method is set up like so, in LandingPageController.cs:
[Route("{unit}/{begdate}/{enddate}")]
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)
{
_unit = unit;
_beginDate = begdate;
_endDate = enddate;
. . .
I have a breakpoint on the "_unit = unit;" line, but it is not being reached; why not? What am I missing here?
The REST controller class under discussion begins like so:
[RoutePrefix("api")]
public class LandingPageController : ApiController
Note: If I use this in the jQuery ("Controller" appended):
url: '#Url.Action("GetQuadrantData", "LandingPageController")'
...both "GetQuadrantData" and "LandingPageController" are red in the IDE (Visual Studio) editor - the letters are red.
OTOH, if I use this (sans "Controller" appended):
url: '#Url.Action("GetQuadrantData", "LandingPage")'
(which has worked for me in the past, leaving the "Controller" off the Controller name), both "GetQuadrantData" and "LandingPage" are UNDERLINED in red, but the font remains the normal color.
UPDATE
Using Nico's link in his comment below, I changed the jQuery "url" line to this:
url: '#Url.Action("GetQuadrantData", "LandingPage", new { httproute = "" })',
...but it still didn't cause the Controller method to be reached.
UPDATE 2
Stepping through the javascript in the (Chrome) browser, I see that the "url" line has been dynamically changed from what it is at design time:
url: '#Url.Action("GetQuadrantData", "LandingPage", new { httproute = "" })',
...to:
url: '/api/LandingPage?action=GetQuadrantData',
I reckon what it should really have been resolved to is more like:
url: '/api/ABUELOS/2016-08-14/2016-08-20',
Am I right? Why isn't it being resolved like so?
If I manually enter that URL in the browser, so that the URL bar reads "http://localhost:52194/api/ABUELOS/2016-08-21/2016-08-27" it works - the method is reached and it "does its thing."
UPDATE 3
I tried this, too:
$(function () {
$("#btnGetData").click(function () {
document.body.style.cursor = 'wait';
$.ajax({
type: "GET",
url: '#Url.Action("GetQuadrantData", "LandingPage")',
success: function (retval) {
$("body").append($(retval));
document.body.style.cursor = 'pointer';
},
error: function () {
alert('error in btnGetData');
}
}); // end AJAX
}); // end click
}); // end ready function
...but only saw "error in btnGetData"
UPDATE 4
My most recent failure is this:
$("#btnGetData").click(function () {
document.body.style.cursor = 'wait';
var unitval = $('#unitName').val();
var begdateval = $('#datepickerFrom').val();
var enddateval = $('#datepickerTo').val();
$.ajax({
type: 'GET',
url: '#Url.Action("GetQuadrantData", "LandingPage")',
data: { unit: unitval, begdate: begdateval, enddate: enddateval },
cache: false,
success: function (returneddata) {
alert($(returneddata));
},
error: function () {
alert('error in ajax');
}
});
});
Again, I see only "error in ajax"
UPDATE 5
Note: The maximum bounty (200 points, I think it is) will be awarded to whoever can solve this dilemma. If more than one person does, then the bounty goes to whoever solves it best (which basically to me means in the most straightforward and easy-to-implement manner.
In the interest of full disclosure and desperation, here is the entire contents (with boring/meaningless parts elided with ellipsis dots) of the first page that displays when the WEB API app runs (from \Views\Home\Index.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>eServices Reporting - Customer Dashboard</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
body {
padding-top: 20px;
padding-bottom: 20px;
background-color: white;
}
. . .
</style>
<script>
$(function () {
$("#btnGetData").click(function () {
document.body.style.cursor = 'wait';
var unitval = "ABUELOS"; //$('#unitName').val();
var begdateval = $('#datepickerFrom').val();
var enddateval = $('#datepickerTo').val();
$.ajax({
type: 'GET',
url: '#Url.Action("GetQuadrantData", "LandingPage")',
data: { unit: unitval, begdate: begdateval, enddate: enddateval },
cache: false,
success: function (returneddata) {
alert($(returneddata));
},
error: function () {
alert('error in ajax');
}
});
});
}); // end ready function
</script>
</head>
<body>
<div class="container body-content">
<div class="jumbotronjr">
<div class="col-md-3" style="margin-top: 0.6cm">
<img src="http://www.proactusa.com/wp-content/themes/proact/images/pa_logo_notag.png" height="86" width="133" alt="PRO*ACT usa logo">
</div>
<div class="col-md-9">
<label class="titletext" style="margin-top: 0.2cm;">Customer Dashboard</label>
<br />
<label class="titletextjr" style="margin-top: -2.2cm;" id="unitName">Craftworks</label>
<label class="cccsfont"> for the week of August 14 </label>
<input class="smalldatepicker" type="date" id="datepickerFrom" name="daterangefrom" value="2016-08-14">
</input>
<label class="cccsfont"> to </label>
<input type="date" class="smalldatepicker" id="datepickerTo" name="daterangeto" value="2016-08-20">
</input>
<button class="btn green smallbutton" id="btnGetData" name="btnGetData">SUBMIT</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-md-12">
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="topleft">
<h2 class="sectiontext">Top 10 Items Purchased</h2>
<table>
<tr>
<th>Item Code</th>
<th>Description</th>
<th class="rightjustifytext">Qty</th>
</tr>
<tr>
<td>101200</td>
<td>ASPARAGUS, STANDARD 11/1#</td>
<td class="rightjustifytext">32</td>
</tr>
<tr>
<td>140200</td>
<td>MUSHROOMS, MEDIUM 10#</td>
<td class="rightjustifytext">20</td>
</tr>
<tr>
<td>140000</td>
<td>MUSHROOMS, BUTTON 10#</td>
<td class="rightjustifytext">14</td>
</tr>
<tr>
<td>127100</td>
<td>LETTUCE, ROMAINE 24 CT </td>
<td class="rightjustifytext">14</td>
</tr>
<tr>
<td>300123</td>
<td>BEANS, GREEN TRIM 2/5# (BAGS)</td>
<td class="rightjustifytext">13</td>
</tr>
<tr>
<td>173100</td>
<td>POTATOES, 50 CT IDAHO</td>
<td class="rightjustifytext">12</td>
</tr>
<tr>
<td>234225</td>
<td>BERRIES, STRAWBERRY 1# CLAM</td>
<td class="rightjustifytext">11</td>
</tr>
<tr>
<td>188500</td>
<td>TOMATOES, GRAPE 12/1 PT</td>
<td class="rightjustifytext">10</td>
</tr>
<tr>
<td>122500</td>
<td>LETTUCE, ICEBERG LINER 24 CT</td>
<td class="rightjustifytext">10</td>
</tr>
<tr>
<td>121050</td>
<td>LETTUCE, GREEN LEAF 24 CT</td>
<td class="rightjustifytext">10</td>
</tr>
</table>
</div>
</div>
<div class="col-md-6">
<div class="topright">
<h2 class="sectiontext">Pricing Exceptions - Weekly Recap</h2>
<label class="redfont cccs">Red denotes Contract Item Overages</label>
</br>
<label class="cccs">For Weyand on the pricing week of - 7/31/2016</label>
<table>
<tr>
<th>PRO*ACT Member</th>
<th class="rightjustifytext">Total Occurrences of Summary Items</th>
<th class="rightjustifytext">Total Summary Exceptions</th>
<th class="rightjustifytext">Total Percentage of Summary Exceptions</th>
</tr>
<tr>
<td style="width:30%">Stern</td>
<td style="width:23%" class="rightjustifytext">205</td>
<td style="width:23%" class="rightjustifytext">2</td>
<td style="width:24%" class="rightjustifytext">99.02%</td>
</tr>
<tr>
<td>Hardies Dallas</td>
<td class="rightjustifytext">1,597</td>
<td class="rightjustifytext">0</td>
<td class="rightjustifytext">100.00%</td>
</tr>
<tr>
<td>Hardies South</td>
<td class="rightjustifytext">612</td>
<td class="rightjustifytext">1</td>
<td class="rightjustifytext">99.84%</td>
</tr>
<tr>
<td>Go Fresh</td>
<td class="rightjustifytext">482</td>
<td class="rightjustifytext">0</td>
<td class="rightjustifytext">100.00%</td>
</tr>
<tr>
<td>Segovias</td>
<td class="rightjustifytext">1,360</td>
<td class="rightjustifytext">2</td>
<td class="rightjustifytext">99.85%</td>
</tr>
<tr>
<td>Potato Spec</td>
<td class="rightjustifytext">1,605</td>
<td class="rightjustifytext">0</td>
<td class="rightjustifytext">100.00%</td>
</tr>
<tr>
<td class="rightjustifytext bold">TOTAL</td>
<td class="rightjustifytext bold">5,861</td>
<td class="rightjustifytext bold">5</td>
<td class="rightjustifytext bold">99.79%</td>
</tr>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="bottomleft">
<h2 class="sectiontext">Forecasted Spend - $9,814.81</h2>
<table>
<tr>
<th>Item Code</th>
<th class="rightjustifytext">Last Week's Usage</th>
<th class="rightjustifytext">This Week's Price</th>
<th class="rightjustifytext">Forecasted Spend</th>
</tr>
<tr>
<td>261650</td>
<td class="rightjustifytext">49</td>
<td class="rightjustifytext">3.14</td>
<td class="rightjustifytext">153.86</td>
</tr>
<tr>
<td>231083</td>
<td class="rightjustifytext">52</td>
<td class="rightjustifytext">1.25</td>
<td class="rightjustifytext">65.00</td>
</tr>
<tr>
<td>398980</td>
<td class="rightjustifytext">46</td>
<td class="rightjustifytext">4.95</td>
<td class="rightjustifytext">227.70</td>
</tr>
<tr>
<td>351135</td>
<td class="rightjustifytext">40</td>
<td class="rightjustifytext">0.75</td>
<td class="rightjustifytext">30.00</td>
</tr>
<tr>
<td>398036</td>
<td class="rightjustifytext">42</td>
<td class="rightjustifytext">3.00</td>
<td class="rightjustifytext">126.00</td>
</tr>
<tr>
<td>208110</td>
<td class="rightjustifytext">42</td>
<td class="rightjustifytext">2.50</td>
<td class="rightjustifytext">105.00</td>
</tr>
<tr>
<td>102800</td>
<td class="rightjustifytext">1835</td>
<td class="rightjustifytext">2.25</td>
<td class="rightjustifytext">4,128.75</td>
</tr>
<tr>
<td>367050</td>
<td class="rightjustifytext">1910</td>
<td class="rightjustifytext">1.95</td>
<td class="rightjustifytext">3,724.50</td>
</tr>
<tr>
<td>173100</td>
<td class="rightjustifytext">66</td>
<td class="rightjustifytext">19.00</td>
<td class="rightjustifytext">1,254.00</td>
</tr>
<tr>
<td class="bold">TOTAL</td>
<td class="bold rightjustifytext">4082</td>
<td class="bold rightjustifytext">--</td>
<td class="bold rightjustifytext">$9,814.81</td>
</tr>
</table>
</div>
</div>
<div class="col-md-6">
<div class="bottomright">
<h2 class="sectiontext">Delivery Performance</h2>
<table>
<tr>
<th>PRO*ACT Distributor</th>
<th>Restaurant Location</th>
<th class="rightjustifytext">Avg Order Amount</th>
<th class="rightjustifytext">Avg Package Count</th>
<th class="rightjustifytext">Total Sales</th>
</tr>
<tr>
<td>Sunrise FL</td>
<td>A1A ALEWORKS - #4405 - ST. AUGUSTINE</td>
<td class="rightjustifytext">$475.78</td>
<td class="rightjustifytext">28.50</td>
<td class="rightjustifytext">$1,903.10</td>
</tr>
<tr>
<td>Sunrise FL</td>
<td>RAGTIME TAVERN - #4404 - ATLANTIC BEACH</td>
<td class="rightjustifytext">$221.46</td>
<td class="rightjustifytext">17.50</td>
<td class="rightjustifytext">$885.82</td>
</tr>
<tr>
<td>Sunrise FL</td>
<td>SEVEN BRIDGES - #4403 - JACKSONVILLE</td>
<td class="rightjustifytext">$367.49</td>
<td class="rightjustifytext">22.67</td>
<td class="rightjustifytext">$1,102.47</td>
</tr>
<tr>
<td>T&T</td>
<td>BIG RIVER - #4201 - CHATTANOOGA</td>
<td class="rightjustifytext">$396.06</td>
<td class="rightjustifytext">22.83</td>
<td class="rightjustifytext">$2,376.34</td>
</tr>
<tr>
<td>T&T</td>
<td>BIG RIVER - #4205 - HAMILTON PL</td>
<td class="rightjustifytext">$424.74</td>
<td class="rightjustifytext">26.00</td>
<td class="rightjustifytext">$1,698.95</td>
</tr>
<tr>
<td class="bold">TOTAL</td>
<td></td>
<td class="bold rightjustifytext">3,770.42</td>
<td class="bold rightjustifytext">23.50</td>
<td class="bold rightjustifytext">$1,592.60</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
UPDATE 6
I know there's more to Arturo's answer than this, but so far just adding this:
config.Routes.MapHttpRoute(
name: "QuadrantData",
routeTemplate: "api/{unit}/{begdate}/{enddate}"
);
...has helped, as the breakpoint in my method is being reached. Unfortunately, it squawks "SyntaxError: Unexpected token < in JSON at position 0"
Personally not a big fan of using #Url.Action in javascript code; this is how I make ajax calls:
Create a hidden field in layout page to store the root url - <input type="hidden" id="hdnRoot" value="#Url.Content("~/")" />
Have a constants json file to keep my client side constants (constants.js) - assigns the hidden field value to serviceRoot variable:
(function () {
window.constants = {
serviceRoot: $("#hdnRoot").val() + "api/",
objectState: {
added: "Added",
modified: "Modified",
unchanged: "Unchanged",
deleted: "Deleted"
},
..other values...
};
})();
Will modify your ajax call as:
var root = window.constants.serviceRoot;
$.ajax({
type: 'GET',
url: root + 'LandingPage/GetQuadrantData/'+unitval+'/'+begdateval+'/'+enddateval,
// data: { unit: unitval, begdate: begdateval, enddate: enddateval },
contentType: 'application/json',
cache: false,
success: function (returneddata) {
},
error: function () {
alert('hey, boo-boo!');
}
});
[RoutePrefix("api")]
public class LandingPageController : ApiController {
[HttpGet]
[Route("GetQuadrantData/{unit}/{begdate}/{enddate}", Name="GetQuadrantDataFromLandingPage")]
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)
Ok, this solution solves your problem but imply some changes in your code:
In the view, when you call Url.Action, you're trying to generate a webapi route from a mvc controller. You can see this question where I say how to do this.
Basically the idea is using Url.RouteUrl with an extra route value httproute = true.
Now, you need to change some parts in your code to be able to use this:
Firstly, you are using attributes to define your web api routes, therefore this routes will be added after the routes defined in your WebApiConfig class, and as I mencioned in the answer of the referenced question, Url.RouteUrl will return the first route that match the route values. So, you need to declare the route in WebApiConfig before the default route:
/* attributes removed */
public class LandingPageController : ApiController
{
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)
{
...
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
/* Route added before the default one */
config.Routes.MapHttpRoute(
name: "QuadrantData",
routeTemplate: "api/{unit}/{begdate}/{enddate}"
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
If you don't do this, the default route will be matched since {id} is optional and unit, begdate and enddate will be passed as query params.
Once fixed this issue, you have another problem, to be able to use Url.RouteUrl you need to know all the route values (unit, begdate, enddate), that are availables only when the script function is executed. But all razor code in your .cshtml is processed in the server when the html is generated for the client.
As you can see, when the javascript is executed you are not executing '#Url.RouteUrl...' or '#Url.Action...', at this time you are just handling a string with value returned when the razor expression was processed.
One thing you can do is pass "template" values to the Url.RouteUrl call, and replace it when the script is executed with the real values:
var url = '#Url.RouteUrl(new
{
unit = "(unit)",
begdate = "(begdate)",
enddate = "(enddate)",
httproute = true
})'
url = url.replace("(unit)", unitval)
.replace("(begdate)", begdateval)
.replace("(enddate)", enddateval)
$.ajax({
type: 'GET',
url: url,
contentType: 'application/json',
cache: false,
success: function (returneddata) {
},
error: function () {
alert('hey, boo-boo!');
}
});
After the replaces the value of the variable url will be like this /api/ABUELOS/2016-08-07/2016-08-13.
If you don't want to move the routes to WebApiConfig, you can set a name in RouteAttribute:
[RoutePrefix("api")]
public class LandingPageController : ApiController
{
[Route("{unit}/{begdate}/{enddate}", Name = "QuadrantData")]
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)
{
...
And specify the route name in Url.RouteUrl call:
var url = '#Url.RouteUrl("QuadrantData", new
{
unit = "(unit)",
begdate = "(begdate)",
enddate = "(enddate)",
httproute = true
})'
This way is less intrusive in your code, but you need to know the name of the route you want to use.
Hope this helps.
You have a few issues with how you are generating the route and how you are trying to access it.
You Web API action is using attribute routing so by default there is no route name to match like in the convention-based routing.
Update the route attribute to include a name to find in the route table.
[RoutePrefix("api")]
public class LandingPageController : ApiController {
[HttpGet]
[Route("{unit}/{begdate}/{enddate}", Name="QuadrantData")]
public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate) {
_unit = unit;
_beginDate = begdate;
_endDate = enddate;
//...other code
}
//...other code
}
Next even though you have the name you also need to include the template parameters in order to get a match from MVC and have it generate the url in the template you defined on the action.
To generate link to Web API, it would look like this
#Url.RouteUrl(routeName : "QuadrantData", routeValues : new { httpRoute = true , unit = "ABUELOS", begdate = "2016-08-07", enddate = "2016-08-13" })
or
#Url.HttpRouteUrl(routeName : "QuadrantData", routeValues : new { unit = "ABUELOS", begdate = "2016-08-07", enddate = "2016-08-13" })
which would add the httpRoute to the route values.
Reference: Construct url in view for Web Api with attribute routing
Now with your approach out of the way, I would suggest the following alternative approach.
KISS principle. Change Web API (REST) endpoint to POST and change its template.
[RoutePrefix("api")]
public class LandingPageController : ApiController {
//eg POST api/QuadrantData
[HttpPost]
[Route("QuadrantData", Name="GenerateQuadrantData")]
public HttpResponseMessage QuadrantData(string unit, string begdate, string enddate) {
_unit = unit;
_beginDate = begdate;
_endDate = enddate;
//...other code
}
//...other code
}
and send the data in the body of a JSON POST request
$(function () {
$("#btnGetData").click(function () {
document.body.style.cursor = 'wait';
var unitval = "ABUELOS"; //$('#unitName').val();
var begdateval = $('#datepickerFrom').val();
var enddateval = $('#datepickerTo').val();
var jsonBody = JSON.stringify({ unit: unitval, begdate: begdateval, enddate: enddateval });
$.ajax({
type: 'POST',
url: '#Url.HttpRouteUrl("GenerateQuadrantData", null)',
contentType: 'application/json',
dataType: 'json',
data: jsonBody,
cache: false,
success: function (returneddata) {
alert($(returneddata));
},
error: function () {
alert('error in ajax');
}
});
});
}); // end ready function
Regarding your point:
If I manually enter that URL in the browser, so that the URL bar reads
"http://localhost:52194/api/ABUELOS/2016-08-21/2016-08-27" it works -
the method is reached and it "does its thing."
Modifying your Ajax call like shown below should solve your problem and will send a GET request to the mapped url (Showing with button click event handler):
$("#btnGetData").click(function () {
var unitval = 'ABUELOS';
var begdateval = '2016-08-21';
var enddateval = '2016-08-27';
$.getJSON("api/" + unitval + "/" + begdateval + "/" + enddateval,
function (Data) {
// do what ever you want with the success response
})
.fail(
function (jqXHR, textStatus, err) {
// do what ever you want with the failed response
});
});
You're only giving your jQuery the controller and action names when it needs the full url to complete the request. Also, your end point has an 'api' prefix. You need your url property to be something like http://localhost:{port}/api/{controller}/{action} if your server is running locally.

Updating record number after deletion in asp.net MVC 4 razor view

I am working on asp.net MVC 4 application. I have created a list using foreach loop and declared a variable to show record number. Each row has a delete icon, which when clicked, deletes that record and hides that row. this works fine except one issue. When user deletes first record or any record in middle of list, I want the record number of all the rows to be updated accordinlgy.
Here is razor view code:
#{
int i = 1;
foreach (var item in cartItem.CartItemsByStore)
{
<tr id="cartrow-#item.CartItemID">
<td class="transaction">#i</td>
<td class="item-details">
<img src="/images/tmp/order-product.jpg" width="63" height="63">
<div class="desc">
<span>
<p>#item.ItemName</p>
</span>
</div>
</td>
<td class="date-time">15 Jun 2014</td>
<td class="action">
X
</td>
</tr>
<tr class="sp" id="sp-#item.CartItemID">
<td colspan="20"></td>
</tr>
i++;
}
}
and here is deletion code:
$(function () {
// Document.ready -> link up remove event handler
$(".removeCartItem").click(function () {
if (confirm("Click OK if you want to delete this record; otherwise, click 'Cancel'")) {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/Cart/DeleteCartItem", { "id": recordToDelete },
function (data) {
// Successful requests get here
$('#cartrow-' + recordToDelete).fadeOut('hide');
$('#sp-' + recordToDelete).fadeOut('hide');
$('#spCartCount').text(data);
$('#row-' + recordToDelete).fadeOut('hide');
});
}
}
});
});
Try this
Partial view : "Store.csthml"
#model IEnumerable<CartItemsByStore>
#{
int i = 1;
foreach (var item in Model)
{
<tr id="cartrow-#item.CartItemID">
<td class="transaction">#i</td>
<td class="item-details">
<img src="/images/tmp/order-product.jpg" width="63" height="63">
<div class="desc">
<span>
<p>#item.ItemName</p>
</span>
</div>
</td>
<td class="date-time">15 Jun 2014</td>
<td class="action">
X
</td>
</tr>
<tr class="sp" id="sp-#item.CartItemID">
<td colspan="20"></td>
</tr>
i++;
}
}
CartController:
public ActionResult ReturnView()
{
//populate model
IEnumerable<CartItemsByStore>model =db.GetItemsByStore();
return PartialView("Store",model)
}
public ActionResult DeleteCartItem(int id)
{
//delete
return RedirectToAction("ReturnView");
}
Main View:
<div id="divStore">
#Html.Partial("Store",cartItem.CartItemsByStore)
</div>
$(".removeCartItem").click(function () {
if (confirm("Click OK if you want to delete this record; otherwise, click 'Cancel'")) {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/Cart/DeleteCartItem", { "id": recordToDelete },
function (data) {
// Successful requests get here
$("#divStore").html(data);
});
}
}
});

MVC Dialog Save Refreshes Table Stops Working

I have been using the code from the article ASP.NET MVC: Ajax Dialog Form Using jQuery UI and it mostly works. I created a grid that lists records and each record has a link to bring up a dialog box to edit the record. After the record has been changed the save button is pressed and the grid is updated using ajax. This works great, but the problem comes after the first record save and the ajax refresh of the grid. If the link to edit the record is clicked again the dialog box doesn't come up, only the partial view is shown. I am guessing, but it appears the partial view that I am trying to bring up again doesn't recognize the parent container. Any ideas?
Display the partial view that contains the grid:
<div id="VehicleHold">
#Html.Partial("_VehicleHold")
</div>
The partial view that makes up the dialog:
#using VehicleWeb.MVCHelpers
#{
int agreementNumber = 0;
var countData = ViewBag.VehicleHoldViewModel as System.Collections.Generic.IEnumerable<VehicleWeb.Model.VehicleHoldViewModel>;
if (countData != null)
{
if (countData.Count() > 0)
{
agreementNumber = (int)countData.DefaultIfEmpty().First().AgreementNumber;
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered">
<thead>
<tr class="table-header">
<th>Edit</th>
<th>Delete</th>
<th>
Type
</th>
<th>
Year
</th>
<th>
Make/Model
</th>
<th>
Plate
</th>
<th>
VIN
</th>
<th>
Num Pass
</th>
</tr>
</thead>
<tbody>
#{
foreach (var item in (ViewBag.VehicleHoldViewModel as System.Collections.Generic.IEnumerable<VehicleWeb.Model.VehicleHoldViewModel>))
{
<tr>
<td>
#Html.ImageDialogLink("UpdateVehicleHold", "Exposure", new { id = item.RID }, "Edit Hold Vehicle", "VehicleHold", Url.Action("RefreshVehicleHold/" + agreementNumber), Html.ResolveUrl("~/pics/edit-button.png"), "Edit Hold Vehicle", "600", "800", new { style = "text-decoration:none;" }, new { style = "text-decoration:none; border-style: none;" })
</td>
<td>
<div title="Vehicle Year">#item.EditType.ToString()</div>
</td>
<td>
<div title="Vehicle Year">#item.AutoYear.ToString()</div>
</td>
<td>
<div title="Vehicle Make/Model">#item.MakeModel.ToString()</div>
</td>
<td>
<div title="Vehicle Plate Number">#item.DistVehNo.ToString()</div>
</td>
<td>
<div title="Vehicle VIN">#item.IDNumber.ToString()</div>
</td>
<td>
<div title="Number Of Passengers">#item.NumOfPassengers.ToString()</div>
</td>
</tr>
}
}
</tbody>
</table>
}
}
}
I am new at asking questions here, so just let me know if you need to see more code.
EDIT:
I don't know if it the position of the jQuery files matters for this. I have been messing around with the position today and haven't found success. I do have the jQuery file on the main form that it used to wire up the dialog box. After the AJAX refreshes the DIV, the edit link seems to loose all knowledge about the any of the parent code. My latest theory is it could be something to do with this code. Could it be because it is in a ready block?
$(document).ready(function () {
$.ajaxSetup({
cache: false
});
// Wire up the click event of any current or future dialog links
$('.dialogLink').on('click', function () {
var element = $(this);
// Retrieve values from the HTML5 data attributes of the link
var dialogTitle = element.attr('data-dialog-title');
var dialogWidth = element.attr('data-dialog-width');
var dialogHeight = element.attr('data-dialog-height');
var updateTargetId = '#' + element.attr('data-update-target-id');
var updateUrl = element.attr('data-update-url');
// Generate a unique id for the dialog div
var dialogId = 'uniqueName-' + Math.floor(Math.random() * 1000)
var dialogDiv = "<div id='" + dialogId + "'></div>";
// Load the form into the dialog div
$(dialogDiv).load(this.href, function () {
$(this).dialog({
modal: true,
resizable: false,
title: dialogTitle,
closeOnEscape: false,
width: dialogWidth,
height: dialogHeight,
buttons: [
{
text: "Save",
icons: { primary: "ui-icon-check" },
click: function () {
// Manually submit the form
var form = $('form', this);
if ($(form).valid()) {
$(form).submit();
$(this).dialog('close');
}
}},
{
text: "Cancel",
icons: { primary: "ui-icon-closethick" },
click: function () {
$(this).dialog('close');
$(this).empty();
}
}]
});
// Enable client side validation
$.validator.unobtrusive.parse(this);
// Setup the ajax submit logic
wireUpForm(this, updateTargetId, updateUrl);
});
return false;
});
});
function wireUpForm(dialog, updateTargetId, updateUrl) {
$('form', dialog).submit(function () {
// Do not submit if the form
// does not pass client side validation
if (!$(this).valid()) {
return false;
}
// Client side validation passed, submit the form
// using the jQuery.ajax form
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
// Check whether the post was successful
if (result.success) {
// Close the dialog
$(dialog).dialog('close');
$(dialog).empty();
// Reload the updated data in the target div
$(updateTargetId).load(updateUrl);
} else {
alert('failure');
// Reload the dialog to show model errors
$(dialog).html(result);
// Enable client side validation
$.validator.unobtrusive.parse(dialog);
// Setup the ajax submit logic
wireUpForm(dialog, updateTargetId, updateUrl);
}
}
});
return false;
});
}
It some times happens when we keep the script in the main view it will bind the event for the first time but won't work after a postback, try moving the script in the partial view, if it doesn't work share some more code and will see what is wrong

Categories