I got this error when I am trying to remove the item from the Cart table.
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: /Panier/RemoveFromCart/1. This URL seems to be fine with me. It should branch to the PanierController at RemoveCart. I don't understand why it is not branching.
Thanks
Index.cshtml
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.4.4.min.js"
type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Document.ready -> link up remove event handler
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", {"id": recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
});
}
});
});
</script>
<h3>
<em>Details</em> du panier:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<table>
<tr>
<th>
Produit
</th>
<th>
Prix (unitaire)
</th>
<th>
Quantite
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.ProduitId">
<td>
#Html.ActionLink(item.Produit.Description,"Details", "Store", new { id =
item.ProduitId }, null)
</td>
<td>
#item.Produit.Prix
</td>
<td id="item-count-#item.ProduitId">
#item.Quantite
</td>
<td>
#Html.ActionLink("Enlever du panier", "RemoveFromCart", "Panier", new { id =
item.ProduitId }, null)
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
PanierController.cs
namespace Tp1WebStore3.Controllers
{
public class PanierController : Controller
{
Tp1WebStoreDBEntities dbProduit = new Tp1WebStoreDBEntities();
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the product to display confirmation
string produitDescription = dbProduit.Paniers
.Single(item => item.PanierId == id).Produit.Description;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(produitDescription) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return View("Details");
}
Your RemoveFromCart controller action is decorated with the [HttpPost] attribute meaning that it is ONLY accessible by POST verbs. But in your view you seem to have generated some action link to it:
#Html.ActionLink(
"Enlever du panier",
"RemoveFromCart",
"Panier",
new { id = item.ProduitId },
null
)
But as you are well aware, an Html.ActionLink translates into an <a> tag in your markup which obviously is sending a GET request to the server when clicked.
So basically you have 3 possibilities here:
Use an Html.BeginForm instead of an ActionLink to refer to this action which would allow you to send a POST request
Get rid of the [HttpPost] attribute from your RemoveFromCart action
AJAXify the anchor which would allow you to use a POST request.
Related
I have my site working so a user can pay via card however now I also need to use PayPal, I can't seem to send the products over from the shopping cart to the paypal controller, each individual product needs to be sent over in the order.
Here is my PayPal controller;
namespace T_shirt_Company_v3.Controllers
{
public class PayPalController : Controller
{
public ActionResult RedirectFromPaypal()
{
return View();
}
public ActionResult CancelFromPaypal()
{
return View();
}
public ActionResult NotifyFromPaypal()
{
return View();
}
public ActionResult ValidateCommand(string RecordId, string CartTotal)
{
bool useSandbox = Convert.ToBoolean(ConfigurationManager.AppSettings["IsSandbox"]);
var paypal = new PayPal(useSandbox);
paypal.item_name = RecordId;
paypal.amount = CartTotal;
return View(paypal);
}
}
}
And my View for checkout that I need the details from;
#model T_shirt_Company_v3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.4.4.min.js"
type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Document.ready -> link up remove event handler
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", {"id": recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
});
}
});
});
</script>
<center>
<h3>
Review your cart:
</h3>
<p class="button">
#using (Html.BeginForm("ValidateCommand", "PayPal"))
{
<input type="submit" name="btnConfirm" value="Check Out with Paypal" />
}
#Html.ActionLink((string)ViewBag.CartStatus, (string)ViewBag.Link, (string)ViewBag.Link2)
#Html.ActionLink("Continue Shopping ", "Index", "Store")
</p>
<div id="update-message">
</div>
<table>
<tr>
<th>
Product Name
</th>
<th>
Price (each)
</th>
<th>
Quantity
</th>
<th></th>
</tr>
#foreach (var item in
Model.CartItems)
{
<tr id="row-#item.RecordId">
<td>
#Html.ActionLink(item.Product.Title,
"Details", "Store", new { id = item.ProductId }, null)
</td>
<td>
#item.Product.Price
</td>
<td id="item-count-#item.RecordId">
#item.Count
</td>
<td>
<a href="#" class="RemoveLink"
data-id="#item.RecordId">
Remove
from cart
</a>
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
</center>
And the controller;
namespace T_shirt_Company_v3.Controllers
{
public class ShoppingCartController : Controller
{
TshirtStoreDB storeDB = new TshirtStoreDB();
//
// GET: /ShoppingCart/
public ActionResult Index()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
// Set up the ViewModel
ShoppingCartViewModel viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal()
};
if (viewModel.CartItems.Any())
{
ViewBag.CartStatus = "Proceed to checkout or ";
ViewBag.Link = "AddressAndPayment";
ViewBag.Link2 = "Checkout";
}
else
{
ViewBag.CartStatus = "Cart is empty please ";
ViewBag.Link = "Index";
ViewBag.Link2 = "Store";
}
// Return the view
return View(viewModel);
}
//
// GET: /Store/AddToCart/5(ID)
public ActionResult AddToCart(int id)
{
// Retrieve the Product from the database
var addedProduct = storeDB.Products
.Single(product => product.ProductId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduct);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
//
// AJAX: /ShoppingCart/RemoveFromCart/5(ID)
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the product to display confirmation
string productName = storeDB.Carts
.Single(item => item.RecordId == id).Product.Title;
// Removes item from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message saying removed from cart
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(productName) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
}
//
// GET: /ShoppingCart/CartSummary
[ChildActionOnly]
public ActionResult CartSummary()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
ViewData["CartCount"] = cart.GetCount();
return PartialView("CartSummary");
}
//test close connection when done
protected override void Dispose(bool disposing)
{
storeDB.Dispose();
}
}
}
Assuming I read your code correctly, you're only rendering the data, you're not sending it (at all).
your form only has a button (it's the only "data" sent)
you need to include the data you rendered as form fields (<input />)
Hth.
As PayPal Api is dependent on a set of operations that must be understood before used, developers should focus on understanding the operations summary, before using the Api, also a sandbox is available for testing before officially using the Api.
You should know how to use the RESTful endpoint structure of PayPal.
You can check the PayPal Api documentation for details on how to integrate your web application with PayPal using REST API Reference.
I'm developing an ASP.NET MVC 5 web with C# and .NET Framework 4.5.1.
I have this form in a cshtml file:
#model MyProduct.Web.API.Models.ConnectBatchProductViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
#if (#Model != null)
{
<h4>Producto: #Model.Product.ProductCode, Cantidad: #Model.ExternalCodesForThisProduct</h4>
using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
#Html.HiddenFor(model => model.Product.Id, new { #id = "productId", #Name = "productId" });
<div>
<table id ="batchTable" class="order-list">
<thead>
<tr>
<td>Cantidad</td>
<td>Lote</td>
</tr>
</thead>
<tbody>
<tr>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].Quantity")</td>
<td>#Html.TextBox("ConnectBatchProductViewModel.BatchProducts[0].BatchName")</td>
<td><a class="deleteRow"></a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<input type="button" id="addrow" value="Add Row" />
</td>
</tr>
</tfoot>
</table>
</div>
<p><input type="submit" value="Seleccionar" /></p>
}
}
else
{
<div>Error.</div>
}
<script src="~/Scripts/jquery-2.1.3.min.js"></script>
<script src="~/js/createBatches.js"></script> <!-- Resource jQuery -->
</body>
</html>
And this is the action method:
[HttpPost]
public ActionResult Save(FormCollection form)
{
return null;
}
And the two ViewModel:
public class BatchProductViewModel
{
public int Quantity { get; set; }
public string BatchName { get; set; }
}
public class ConnectBatchProductViewModel
{
public Models.Products Product { get; set; }
public int ExternalCodesForThisProduct { get; set; }
public IEnumerable<BatchProductViewModel> BatchProducts { get; set; }
}
But I get this in FormCollection form var:
But I want to get an IEnumerable<BatchProductViewModel> model:
public ActionResult Save(int productId, IEnumerable<BatchProductViewModel> model);
If I use the above method signature both parameters are null.
I want an IEnumerable because user is going to add more rows dynamically using jQuery.
This is jQuery script:
jQuery(document).ready(function ($) {
var counter = 0;
$("#addrow").on("click", function () {
counter = $('#batchTable tr').length - 2;
var newRow = $("<tr>");
var cols = "";
var quantity = 'ConnectBatchProductViewModel.BatchProducts[0].Quantity'.replace(/\[.{1}\]/, '[' + counter + ']');
var batchName = 'ConnectBatchProductViewModel.BatchProducts[0].BatchName'.replace(/\[.{1}\]/, '[' + counter + ']');
cols += '<td><input type="text" name="' + quantity + '"/></td>';
cols += '<td><input type="text" name="' + batchName + '"/></td>';
cols += '<td><input type="button" class="ibtnDel" value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function (event) {
$(this).closest("tr").remove();
counter -= 1
$('#addrow').attr('disabled', false).prop('value', "Add Row");
});
});
Any idea?
I have checked this SO answer, and this article but I don't get my code working.
You need to generate the controls for the collection in a for loop so they are correctly named with indexers (note that property BatchProducts needs to be IList<BatchProductViewModel>
#using (Html.BeginForm("Save", "ConnectBatchProduct", FormMethod.Post))
{
....
<table>
....
#for(int i = 0; i < Model.BatchProducts.Count; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].Quantity)</td>
<td>#Html.TextBoxFor(m => m.BatchProducts[i].BatchName)</td>
<td>
// add the following to allow for dynamically deleting items in the view
<input type="hidden" name="BatchProducts.Index" value="#i" />
<a class="deleteRow"></a>
</td>
</tr>
}
....
</table>
....
}
Then the POST method needs to be
public ActionResult Save(ConnectBatchProductViewModel model)
{
....
}
Edit
Note: Further to your edit, if you want to dynamically add and remove BatchProductViewModel items in he view, you will need to use the BeginCollectionItem helper or a html template as discussed in this answer
The template to dynamically add new items would be
<div id="NewBatchProduct" style="display:none">
<tr>
<td><input type="text" name="BatchProducts[#].Quantity" value /></td>
<td><input type="text" name="BatchProducts[#].BatchName" value /></td>
<td>
<input type="hidden" name="BatchProducts.Index" value ="%"/>
<a class="deleteRow"></a>
</td>
</tr>
</div>
Note the dummy indexers and the non-matching value for the hidden input prevents this template posting back.
Then the script to add a new BatchProducts would be
$("#addrow").click(function() {
var index = (new Date()).getTime(); // unique indexer
var clone = $('#NewBatchProduct').clone(); // clone the BatchProducts item
// Update the index of the clone
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));
$("table.order-list").append(clone.html());
});
In your Post Methode you receive "MyProduct.Web.API.Models.ConnectBatchProductViewModel" as Parameter.
Use the existing model for the Post methode.
Why do you want a IEnumerable from your model? there is only one available including the id in the model.
you can visit this article for complete source code with a video tutorial.
you have to create an action first, from where we can pass the list of object
[HttpGet]
public ActionResult Index()
{
List<Contact> model = new List<Contact>();
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
model = dc.Contacts.ToList();
}
return View(model);
}
then we need to create a view for that action
#model List<UpdateMultiRecord.Contact>
#{
ViewBag.Title = "Update multiple row at once Using MVC 4 and EF ";
}
#using (#Html.BeginForm("Index","Home", FormMethod.Post))
{
<table>
<tr>
<th></th>
<th>Contact Person</th>
<th>Contact No</th>
<th>Email ID</th>
</tr>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td> #Html.HiddenFor(model => model[i].ContactID)</td>
<td>#Html.EditorFor(model => model[i].ContactPerson)</td>
<td>#Html.EditorFor(model => model[i].Contactno)</td>
<td>#Html.EditorFor(model => model[i].EmailID)</td>
</tr>
}
</table>
<p><input type="submit" value="Save" /></p>
<p style="color:green; font-size:12px;">
#ViewBag.Message
</p>
}
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
}
and then we have to write code for save the list of object to the database
[HttpPost]
public ActionResult Index(List<Contact> list)
{
if (ModelState.IsValid)
{
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
foreach (var i in list)
{
var c = dc.Contacts.Where(a =>a.ContactID.Equals(i.ContactID)).FirstOrDefault();
if (c != null)
{
c.ContactPerson = i.ContactPerson;
c.Contactno = i.Contactno;
c.EmailID = i.EmailID;
}
}
dc.SaveChanges();
}
ViewBag.Message = "Successfully Updated.";
return View(list);
}
else
{
ViewBag.Message = "Failed ! Please try again.";
return View(list);
}
}
using(Html.BeginForm())
{
// code here
}
While to Post form Data all tags must be included form tag.
Following the principle of DRY, you can create one EditorTemplate for that purpose.
Steps:
1- In Views > Shared > Create new folder named (EditorTemplates)
2- Create a view inside your newly created EditorTemplates folder , the view's model should be BatchProductViewModel according to the OP example. Place your code inside the Editor view. No loop or index is required.
An EditorTemplate will act similar to a PartialView for every child entity but in a more generic way.
3- In your parent entity's view, call your Editor :
#Html.EditorFor(m => m.BatchProducts)
Not only this provides a more organized views, but also let's you re-use the same editor in other views as well.
I have a small problem.
My action is :
public ViewResult SearchForRooms(int HotelDDL)
{
List<Room> roomsInHotel = bl.ReturnRoomsPerHotel(HotelDDL);
return View(roomsInHotel);
}
Here is the jquery that is calling the action:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
});
});
});
</script>
And finally, here is the View that should be called:
#model IEnumerable<RoomReservation.Entities.Entities.Room>
#{
ViewBag.Title = "Search";
}
<h2>Result</h2>
<table>
<tr>
<th>
City
</th>
<th>
Hotel
</th>
<th>
Room label
</th>
<th>
Number of beds
</th>
<th>
Price per night
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelitem=>item.Hotel.City.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Hotel.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.NumberOfBeds)
</td>
<td>
#Html.DisplayFor(modelItem => item.PricePerNight)
</td>
</tr>
}
</table>
Everthing is working ok (databse return all rooms correctly) except final view rendering.
I have tried Phil's tool but it doesn't give me any suspicious hints:
RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
So, why is it not showing after jscript send it's post method to SearchForRooms()?
Thank you
P.S. If you need any other piece of code please just say so.
Note that doing an ajax post will not refresh or redirect the page like a classic post would.
The view is not showing because there is no where to place it. You post successfully, and return a view successfully but then do nothing with it. If you want to show the returned view, then you have to append it to the dom somehow. Here is a common method:
<div id="successDiv"></div>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
});
});
</script>
Comment Response
#TunAntun - You should use a classic post if you want the view to have its own page. There is no way to accomplish this from ajax. You could do this with javascript though
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
would become
var postForm = document.createElement("form");
postForm.setAttribute("method","post");
postForm.setAttribute("action","/Home/SearchForRooms");
var postVal = document.createElement("input");
postVal.setAttribute("type","hidden");
postVal.setAttribute("name","HotelDDL");
postVal.setAttribute("value",$("#HotelDDL option:selected").val() );
postForm.appendChild(postVal);
document.body.appendChild(postForm);
$(postForm).submit();
This will dynamically issue the post you wanted. Then in your controller it will properly redirect or return a view. It is highly suggested that when returning a view from a [HttpPost] that you use RedirectToAction and then return the view from a [HttpGet] method in order to prevent refresh from reposting old data.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
MVC(3) handleUpdate
I'm (slowly) learning how to use MVC 3 and at the moment I'm having a looking at the MvcMusicStore tutorial app on the asp.net website.
Right now I'm trying to understand how HttpPost works. From what I can gather, the user performs whatever actions they want in their browser and then with the use of jQuery, the data is posted back to the server (to the corresponding function with [HttpPost] attribute) and then in this case, a json result is sent back to the browser which handles this and updates elements accordingly.
I understand this fine, but in the particular snippet of code I'm looking at, I can't understand how the 'handleUpdate()' function is being hit when there appear to be no calls made from either the js or the server-side code. Is there something I'm missing here? Anyway here is the front-end:
#model MvcMusicStore.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Document.ready -> link up remove event handler
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", { "id": recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
});
}
});
});
function handleUpdate() {
// Load and deserialize the returned JSON data
var json = context.get_data();
var data = Sys.Serialization.JavaScriptSerializer.deserialize(json);
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
}
</script>
<h3>
<em>Review</em> your cart:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<table>
<tr>
<th>
Album Name
</th>
<th>
Price (each)
</th>
<th>
Quantity
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.RecordId">
<td>
#Html.ActionLink(item.Album.Title, "Details", "Store", new { id = item.AlbumId }, null)
</td>
<td>
#item.Album.Price
</td>
<td id="item-count-#item.RecordId">
#item.Count
</td>
<td>
Remove from cart
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td>
</td>
<td>
</td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
and here is the (relevant) server-side code:
//
// AJAX: /ShoppingCart/RemoveFromCart/5
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the album to display confirmation
string albumName = storeDB.Carts
.Single(item => item.RecordId == id).Album.Title;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(albumName) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
}
I can see that the handleUpdate() manipulates the DOM based on the returned JSON, but I can't figure out for the life of me how it's being called? Is there some jQuery magic going on or have I completely misunderstood how this all works?
Thanks!
It's not being called.
The relevant code on the client side that calls the RemoveFromCart method on the server side is this:
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", { "id": recordToDelete },
function (data) {
// Handle result.
});
}
Note the URL is /ShoppingCart/RemoveFromCart, which maps to the URL route for the RemoveFromCart method.
The jQuery post method is being used to make the call to the method on the controller, and then a closure (indicated by the function() { ... }) is passed, not the handleUpdate method.
Okay so, I have a form that is posting using ajax...
<% using(Ajax.BeginForm(new AjaxOptions() { OnBegin="onBegin", OnSuccess = "onSuccess", OnFailure="onFailure" })) { %>
On the server side I am passing back from the controller a Json object. Now, when the OnSuccess event fires I can get to the Json object by using "result.get_response().get_object()"...
My question is, I need to be able to refresh a partial on the page with a list of items that are in the Json object...
Thoughts on how I can do this..?
Use jQuery, and spin through the returned JSON object, building whatever you like.
Example:
$.each(json, function(i, item) {
//Add a dinner to the list on the right
$('#dinnerList').append($('<li/>')
.attr("class", "dinnerItem")
.append($('<a/>').attr("href", "/Dinners/Details/" + item.ID)
.html(item.Name)).append("SomeThing"));
});
I think that you will find the below code helpful.
Firstly, create an AJAX form with
RefreshAjaxList: the name ajax action of current controller
string.empty (optional)
AJAX option
id of form (optional)
when click status, we will edit the status call server to update the status
after edit the status, we call submit button to call RefreshAjaxList; the button is display:none
in this example, I have one controller: AjaxController with 2 actions:
public ActionResult UpdateStatus(int contactId, Status contactStatus)
{
ContactRepository repo = new ContactRepository();
repo.UpdateStatus(contactId, contactStatus);
return Json("success:true");
}
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("RefreshAjaxList")]
public ActionResult RefreshContact()
{
ContactRepository repo = new ContactRepository();
IList<Contact> list = repo.List();
return PartialView("AjaxUc/AjaxList", repo.List());
}
JavaScript:
var status = { active: 1, inactive: 0 };
function editStatus(cell, id, active) {
if (active)
cell.innerHTML = "<input type='radio' checked='true' name='active" + id + "' onclick='updateStatus(this, " + id + ", true);'>Active</input>" +
"<input type='radio' name='active" + id + "' onclick='updateStatus(this, " + id + ", false);'>Inactive</input>";
else
cell.innerHTML = "<input type='radio' name='active" + id + "' onclick='updateStatus(this, " + id + ", true);'>Active</input>" +
"<input type='radio' checked='false' name='active" + id + "' onclick='updateStatus(this, " + id + ", false);'>Inactive</input>";
}
function updateStatus(radio, id, active) {
if (radio.checked != active) {
if (confirm("Do you want to change the status of the contract?")) {
if (active)
cStatus = status.active;
else
cStatus = status.inactive;
$.ajax({
url: 'Ajax/UpdateStatus',
dataType: "json",
data: { contactId: id, contactStatus: cStatus },
success: function(html) {
jQuery("#divAjaxList").submit();
},
error: function(request, desc, ex) {
alert(desc);
}
});
}
}
}
Your ASP script:
<% using (Ajax.BeginForm("RefreshAjaxList", "abc", new AjaxOptions() { UpdateTargetId = "divContent" }, new { #id = "divAjaxList" }))
{%>
<div id="divContent">
<table>
<tr>
<th>
</th>
<th>
Id
</th>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
Phone
</th>
<th>
Email
</th>
<th>
Status
</th>
</tr>
<% foreach (var item in Model)
{ %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { id = item.Id })%>
|
<%= Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%= Html.Encode(item.Id)%>
</td>
<td>
<%= Html.Encode(item.FirstName)%>
</td>
<td>
<%= Html.Encode(item.LastName)%>
</td>
<td>
<%= Html.Encode(item.Phone)%>
</td>
<td>
<%= Html.Encode(item.Email)%>
</td>
<td ondblclick="editStatus(this,<%=item.Id %>, <%= item.Status.GetHashCode() %>);">
<%= item.Status== Status.Active ? "Active" :"Inactive" %>
</td>
</tr>
<% } %>
</table>
<input type="submit" id="refresh" style="display:none" />
</div>
<% } %>
For more info, mail to pnguyen2#firstlook.com for further discussion.
Hope this can help u.
create the user control for the list of items to be displayed and render it as partial by passing the json data to the UC. This will refresh partially
You can also use JTemplate to render JSON data