How to Post multiple rows with AngularJS - javascript

I am trying to submit a form with multiple table rows. I have found examples online and have managed to send the table data to the AngularJS controller but I cannot figure out how to send that data to the apiController.
The form is a Purchase Order that has a table with the Purchase Order Details. I have chained the submit button with the both the Purchase Order and Purchase Order Detail submit functions.
<table class="table" style="">
<tbody>
<tr class="pointer no_selection" ng-repeat="newJobItem in rows">
<td style="width:50px"><input style="width:20px" type="checkbox" class="form-control"></td>
<td style="width:200px">{{newJobItem.JobItemName}}</td>
<td style="width:480px">{{newJobItem.JobItemDescription}}</td>
<td style="width:100px">{{newJobItem.JobItemMatSize}}</td>
<td style="width:150px">{{newJobItem.JobItemQuantity}}</td>
<td style="width:50px">{{newJobItem.JobItemUOM}}</td>
<td style="width:150px">${{newJobItem.JobItemPrice | number : fractionSize}}</td>
<td style="width:20px"><input type="button" value="X" class="btn btn-primary btn-sm" ng-click="removeRow(newJobItem.JobItemName)" /></td>
</tr>
</tbody>
</table>
<input style="margin-right:30px" id="btn-width" type="button" class="btn btn-default" ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()" value="Submit"/>
Controller
//Post Purchase Order
$scope.PODate = new Date(); //Todays Date
$scope.POId = Math.floor(Math.random() * 1000000001) //PurchaseOrder Id Generator
$scope.submitPurchaseOrder = function () {;
var data = {
JobId: $scope.job.JobId,
POId : $scope.POId,
PONumber: $scope.currentItem.PONumber,
PODate: $scope.PODate,
POAmount: $scope.currentItem.POAmount,
POLastPrintDate: $scope.currentItem.POLastPrintDate,
POEmail: $scope.POEmail,
POPrint: $scope.currentItem.POPrint,
POFaxNumber: $scope.POFaxNumber,
PONotes: $scope.currentItem.PONotes,
POCreatedBy: $scope.currentItem.POCreatedBy,
PODeliveryDate: $scope.currentItem.PODeliveryDate,
POShipVia: $scope.currentItem.POShipVia,
POShowPrices: $scope.currentItem.POShowPrices,
POCostCode: $scope.currentItem.POCostCode,
POApprovedNumber: $scope.currentItem.POApprovedNumber,
POBackorder: $scope.currentItem.POBackorder,
}
$http.post('/api/apiPurchaseOrder/PostNewPurchaseOrder', data).success(function (data, status, headers) {
console.log(data);
var tmpCurrentItem = angular.copy($scope.currentItem);
$scope.purchaseOrderArray.push(tmpCurrentItem)
angular.copy({}, $scope.currentItem);
//hide modal window
$scope.openNewPurchaseOrderModal.then(function (m) {
m.modal('hide');
});
});
};
//Post Purchase Order Detail
$scope.newJobItem = {};
$scope.submitPurchaseOrderDetail = function () {
var index = 0;
$scope.rows.forEach(function (newJobItem) {
console.log('rows #' + (index++) + ': ' + JSON.stringify(newJobItem));
});
var data = {
POId: $scope.POId,
PODItem: $scope.newJobItem.JobItemName,
PODDescription: $scope.newJobItem.JobItemDescription,
PODNotes: $scope.PODNotes,
PODUOM: $scope.newJobItem.JobItemUOM,
PODPrice: $scope.newJobItem.JobItemPrice,
PODQuantity: $scope.newJobItem.JobItemQuantity,
PODAmount: $scope.PODAmount,
PODMatSize: $scope.newJobItem.JobItemMatSize,
PODSection: $scope.PODSection,
PODMultiplier: $scope.PODMultiplier,
PODBackOrder: $scope.PODBackOrder
}
$http.post('/api/apiPurchaseOrderDetail/PostNewPurchaseOrderDetail', data).success(function (data, status, headers) {
console.log(data); window.top.location.reload();
});
};
Purchase Order Detail ApiController
// POST api/<controller>
public async Task<IHttpActionResult> PostnewPurchaseOrderDetail([FromBody]PurchaseOrderDetail newPurchaseOrderDetail)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
using (var context = new ApplicationDbContext())
{
context.PurchaseOrderDetails.Add(newPurchaseOrderDetail);
await context.SaveChangesAsync();
return CreatedAtRoute("PurchaseOrderDetailApi", new { newPurchaseOrderDetail.PODId }, newPurchaseOrderDetail);
}
}
Update
Changed as suggested
// POST api/<controller>
public HttpResponseMessage PostNewPurchaseOrderDetail(int id, PurchaseOrderDetail newPurchaseOrderDetail)
{
ApplicationDbContext db = new ApplicationDbContext();
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
if (id != newPurchaseOrderDetail.PODId)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(newPurchaseOrderDetail).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}

You are executing two functions, each making an asyncronous request:
ng-click="submitPurchaseOrder();submitPurchaseOrderDetail()"
This doesn't feel right - both requests are sent in parallel and none is waiting for the other. Do you really mean it?
I would either package and send all data in a single request (also better experience for the user), then let the server deal with un-packaging. Or, if one request needs to wait for another, chain the Promises returned by $http:
$http.post(...)
.then(function(){
return $http.post(...);
})
.success(...)
.fail(...);
or use $q.all(promises) instead.
EDIT.
Also a cleaner and more scalable approach is to use dedicated Angular Service to post your data, see e.g. example on Angular Homepage

I'm not sure about your approach, to me it would be better to join both requests, purchaseOrder and the detail into a single call, you can still separate the data as you may feel convenient.
calling both functions at the same time could have unexpected behaviors since both are running asynchronously you may find 'race conditions'.
try to send a single request and organize how you are going to post the information like
var data = {
JobId: $scope.job.JobId, //common data between the order and the detail
POId: $scope.POId,
Order:{
PONumber: $scope.currentItem.PONumber,
PODate: $scope.PODate,
POAmount: $scope.currentItem.POAmount,
POLastPrintDate: $scope.currentItem.POLastPrintDate,
POEmail: $scope.POEmail,
POPrint: $scope.currentItem.POPrint,
POFaxNumber: $scope.POFaxNumber,
PONotes: $scope.currentItem.PONotes,
POCreatedBy: $scope.currentItem.POCreatedBy,
PODeliveryDate: $scope.currentItem.PODeliveryDate,
POShipVia: $scope.currentItem.POShipVia,
POShowPrices: $scope.currentItem.POShowPrices,
POCostCode: $scope.currentItem.POCostCode,
POApprovedNumber: $scope.currentItem.POApprovedNumber,
POBackorder: $scope.currentItem.POBackorder,
},
Detail:{
PODItem: $scope.newJobItem.JobItemName,
PODDescription: $scope.newJobItem.JobItemDescription,
PODNotes: $scope.PODNotes,
PODUOM: $scope.newJobItem.JobItemUOM,
PODPrice: $scope.newJobItem.JobItemPrice,
PODQuantity: $scope.newJobItem.JobItemQuantity,
PODAmount: $scope.PODAmount,
PODMatSize: $scope.newJobItem.JobItemMatSize,
PODSection: $scope.PODSection,
PODMultiplier: $scope.PODMultiplier,
PODBackOrder: $scope.PODBackOrder
}
}
you'll need to map the purchase order and the detail to a single dto object in your api controller.
just as a sidenote, I'd recommend you to use a stronger unique identifier rather than using a random number.

I think the trouble is with you controller try using this and also can you please elaborate the trouble.Does your APIcontroller is never found by your controller ?
public class Oders : ApiController // in your controller class
{
public HttpResponseMessage Post(PurchaseOrderDetails newOrder)
{
//your code
}
}

Related

How to dynamically show a button based on conditions where the value being used to determine what button to show isn't known until it's clicked?

If someone has a better title feel free to edit. I inherited a project from a developer who is leaving the company and I'm scratching my head trying to find a solution to a problem the existing code provides.
Code from the view:
<div>
<table class="table">
<tr>
<th class="border-bottom border-top-0">Action</th>
</tr>
#foreach (Step actionItem in Model.Steps)
{
#if (actionItem.HasRun == false)
{
<tr class="border-top-0">
<td>
#if (actionItem.ReturnsInfo == true)
{
<input type="button" value="Run Check" onclick="loadProcessingFeedbackPartial('#actionItem.StepID', '#Model.Client.DatabaseConnectionString' )" />
}
else
{
<input type="submit" value="Run Check" name="btnRunStoredProcedure" asp-action="CallStepStoredProcedure" asp-route-StepID="#actionItem.StepID" asp-route-StepCompleted="#actionItem.HasRun" />
}
</td>
</tr>
break;
}
}
</table>
</div>
Javascript being called from the button click:
<script type="text/javascript">
function loadProcessingFeedbackPartial(x, y) {
var url = '#Url.Action("ViewProcessingFeedBackPartial", "Client")';
var stepId = x;
var databaseConnectionString = y;
$("#processingFeedbackPartialDiv").load(url, { stepId, databaseConnectionString },
function () {
$("#confirmButton").removeAttr("style");
});
}
</script>
Controller action:
public IActionResult ViewProcessingFeedBackPartial(int StepId, string DatabaseConnectionString)
{
FeedbackDetails feedbackDetails = new FeedbackDetails();
feedbackDetails.Data = _clientProcessingService.GetProcessingFeedbackDetails(StepId, DatabaseConnectionString);
return PartialView("_ViewFeedback", feedbackDetails);
}
The button in the view has an Onclick event that goes to the Javascript function, which loads a partial view with the data from the controller calling a service method. Here's where the problem is. If no rows are returned, I want to bypass the partial being drawn entirely.
So I changed the controller action around a bit to include a condition where if the feedbackDetails.Data has 0 rows to just call a different method from the service, process as normal, but return the View instead of a partial.
public IActionResult ViewProcessingFeedBackPartial(int StepId, string DatabaseConnectionString, int ClientId)
{
FeedbackDetails feedbackDetails = new FeedbackDetails();
feedbackDetails.Data = _clientProcessingService.GetProcessingFeedbackDetails(StepId, DatabaseConnectionString);
if(feedbackDetails.Data.Rows.Count == 0)
{
_clientProcessingService.RunProcessStepConfirmation(DatabaseConnectionString, StepId, ClientId, "No information returned, automatically proceeding to next step.");
return RedirectToAction("Processing", new { Id = ClientId });
}
return PartialView("_ViewFeedback", feedbackDetails);
}
This "worked", except since in the view it's being called in a Javascript function that loads a partial regardless, the view is returned inside that partial instead of the view being returned.
But I'm unsure how to fix this because without first clicking the button and attempting to populate that collection with data, I don't know if it's empty (and skip the partial) or it has rows (and draw the partial).
I attempted creating an intermediary controller action that returns a boolean and attempted to use the result of that inside the javascript function to either draw the partial or skip it based on the bool, but I'm not really the greatest at Javascript so I wasn't able to get it to work.
I'm unsure if the way to solve this involves creating logic that displays multiple buttons that route to different controller actions or javascript functions or just handling it all via Javascript somehow.
What would be a good way to go about solving this?
#Mkalafut, your jQuery function is loading the controller result directly into "#processingFeedbackPartialDiv" regardless of the result received. Better to pull this initially into a variable, then add some simple logic to decide what to do next. Potentially the controller can help by returning a null result that is easy to identify.
e.g.
$.get("url", { stepId, databaseConnectionString }, function (data) {
var result = data;
// Some example conditional logic - adjust as required
if (result != null){
$("#processingFeedbackPartialDiv").html(result);
$("#confirmButton").removeAttr("style");
}
});
Remember, jQuery load & get are both just shorthand functions for ajax, so if needs be you can customise the code further to get the flexibility you need.
https://api.jquery.com/jQuery.get/
https://api.jquery.com/load/

Browser crashed when angularjs supply data on HTML datalist

I have a html datalist that supplies list of account name which around 14k+, it works fine but any browser that I used will not respond first then successfully supplied the data in datalist using ng-repeat. In worst case the browser crashed.
C# backend
public JsonResult getCollateralAccount() {
List<collateralAccount> accountlist = new List<collateralAccount>();
sqlHelper = new QueryHelper();
SqlParameter[] parameterList = { };
var table = sqlHelper.ExecuteQuery("collateralGetListOfAccount", System.Data.CommandType.StoredProcedure, parameterList).Tables[0];
accountlist = table.AsEnumerable().Select(row => new collateralAccount
{
Id = row.Field<int>("Id"),
name = row.Field<string>("name")
}).ToList();
return new JsonResult { Data = accountlist, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Service
getCollateralAccount: function (data) {
var $getCollateralAccount = $http.get('/Collatera/getCollateralAccount').
success(function (data) {
return data;
});
return $getCollateralAccount;
}
Controller
$scope.listofCAccount = [];
CollateralService.getCollateralAccount().then(function(msg){
if(msg.data.length>0){
$scope.listofCAccount = msg.data;
}
});
View
<input id="username" type="text" class="form-control width100" list="UsersName" ng-model="user.name" required/>
<datalist id="UsersName">
<option ng-repeat="acc in accListContainer track by $index" value="{{acc.name}}" data-val="{{acc.name}}"></option>
</datalist>
Can anyone help me how to stop my browser from crashing or not responding?
success/error has been deprecated, also you are using then at your controller, so just change your service as below(return Promise of $http.get directly).
getCollateralAccount: function (data) {
return $http.get('/Collatera/getCollateralAccount');
}
14K result in an ng-repeat is for sure not what any user would like to see.
You could try limitTo filter if this applies to you. You can use it like this:
ng-repeat="acc in accListContainer | limitTo:10 track by $index"
For more interesting approaches see: How to improve performance of ngRepeat over a huge dataset (angular.js)?

Debugging AngularJS, Splicing List

Kind of 2 questions in 1 here, Finding Angular really hard to debug.
Seems like stuff just magically breaks and fixes itself.
For example I have an ajax call to delete a "site".
Worked fine, I was happy with it so I decided to add a bit of code to splice it from the list. Now my id come through as null.
I put a break point in In google chrome for my onClick() but it never gets hit.
Using MVC5 and angular
HTML
<table class="table">
<tr>
<th>
Value
</th>
<th></th>
</tr>
<tr ng-repeat="site in sites">
<td>
{{site.Value}}
</td>
<td>
<button id="delete-{{site.Id}}" class="btn btn-primary" ng-click="deleteSite(site.id)">Delete</button>
</td>
</tr>
​
Angular controller
ngApp.controller('siteController', ['$scope', '$http', '$location', function ($scope, $http, $location) {
$http.post(ROOT + '/Site/LoadAll/')
.success(function (result) {
$scope.sites = result;
}).
error(function (data, status, headers, config) {
// log to console?
});
$scope.deleteSite = function (id) {
//$http.post(ROOT + 'SiteList/Delete/', JSON.stringify(id)) //null id
//$http.post(ROOT + 'SiteList/Delete/', id) //Invalid JSON primitive: 5f6d794f-bf13-4480-9afd-3b10d7b6ae32.
//$http.post(ROOT + 'Site/Delete/', { id: id } )
$http.post(ROOT + '/Site/Delete/' + id)
.success(function (result) {
// log to console?
}).
error(function (data, status, headers, config) {
// log to console?
});
for (var i = $scope.sites.lenght - 1; i >= 0; i--)
{
if ($scope.sites[i].id == id)
{
$scope.sites.splice(i,1)
}
}
//for(var i=0)
// find the $scope.sites that matches the id
// javascript re mpve that elemtne from the array
};}]);
Server controller
public JsonResult Delete(Guid id)
{
try
{
//var convertedID = new Guid(id);
_siteService.Delete(id);
return Json("OK", JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json("Error" + e.Message);
}
}
So can anybody spot an issue here and how do you guys debug your Angular?
It seems there is a javascript, a http request and a asp.net mvc modelbinding flow to debug here.
In javascript i would add a few console.log statements. I use chrome for development and debugging. You could add a console.log('site', i, id, $scope.sites); in your "splice loop" to check if you get the expected result.
Http traffic can be monitored with chrome in the network tab or you can download fiddler2. Both will take a little playing around with to understand but once you get it, it's pretty straightforward. Pay attention to your form values in the request. It should hold a key id with the id value of the site.
In your asp.net mvc application you can set a breakpoint on your first { line of your action method and inspect the id variable to see if that holds the expected value.

Asp Net MVC 5 refresh a table in a partial view

So i ran into a little problem and i am having a hard time understanding what I should do to get the result I want/need.
So my application is supposed to show the route a certain object made in the last 2 hours. When the user loads the app they see several points scattered through out the map and when they click on one of those objects the route it made in the last 2 hours is shown, and a table I have is supposed to be updated with those coordinates. Now I make the call to fill the partial view when I get all the locations the object went to in the controller method.
this is how I start all of this (when the user clicks a point the following is executed)
(I am using openlayers 3 but it is irrelevant to this question)
$.ajax({
type: "GET",
url: '/Controller/GetRoutes',
dataType: "json",
success: function (result) {
alert('Added');
var layerLines = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.LineString(routes, 'XY'),
name: 'Line'
})
]
})
});
map.addLayer(layerLines);
},
error: function (xhr, ajaxOptions, thrownError) {
//some errror, some show err msg to user and log the error
alert(xhr.responseText);
}
});
So as you can see from this code the method GetRoutes() is going to be responsible for getting the information on where the object has been to.
This is the controller (I omitted most of the code thats responsible for drawing the actual routes since its quite a bit chunky)
[HttpGet]
public JsonResult GetRoutes()
{
var lastpoints = get an arraylist with all the points I want
var name = get the name of the object
RouteInformation(lastPoints,name);
return Json(lastPoints, JsonRequestBehavior.AllowGet);
}
I know I should probably change something here but i do not know what.
The method that gives me the last points is not mine, but I am required to use it so I have no other choice but to accept the arrayList it returns to me.
this is the RouteInformation method
public ActionResult RouteInformation(ArrayList routeList, string name )
{
List<ObjPoint> routes = routeList.OfType<ObjPoint>().ToList();
List<ObjRoute> objRoutes = new List<ObjRoute>();
objRoutes.Add(new ObjRoute()
{
name = name,
ObjPoints = routes
});
return PartialView("RouteDetailsView", objRoutes);
}
My issue is updating/refreshing that table, I have it in a partial view but I have no idea on what I have to do in order update that table with the information I want to display (i can get that information I just can´t seem to show it).
ObjPoint is composed of latitude,longitude, date, time.
This is the ObjRoute model
public class ObjRoute
{
public string name { get; set; }
public List<ObjPoint> ObjPoints { get; set; }
}
And now the Views ...
this is how the "main view" calls the partial view
<div>
#Html.Partial("routeDetailsView")
</div>
And this is my partial view
#model webVesselTracker.Models.ObjRoute
#{
ViewBag.Title = "RouteDetailsView";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
<table id="routeTable" class="table">
<tr>
<th>
Name
</th>
<th>
Latitude
</th>
<th>
Longitude
</th>
<th></th>
</tr>
#if (Model != null) {
foreach (var item in Model.ObjPoints)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Latitude)
</td>
<td>
#Html.DisplayFor(modelItem => item.Longitude)
</td>
</tr>
}
}
else
{
<tr>
<td>
No object has been selected, please select one
</td>
</tr>
}
</table>
</div>
Now I know I could probably do this by adding some sort of json request in the js file and from there on build the table, but I would like to know how to do this with Razor and where I have gone wrong in the code/logic.
Am I supposed to add some ajax elsewhere?
So to summarize this:
-User sees points.
-User clicks point to see the route it made.
-App draws the route and then sends the route information to a method table so it can be added to the table
the user can see that information
Thank you for your time and if I missed something please point it out so I can fix or explain it better.
I finally gave up and looked into knockout.js, it managed to solve all the issues I was having
knockout.js

partial view is not display back anything error 404 is generated

I am trying to fix this problem I got an error 404 on the partial view path url: localhost:49259/Panier/TableContent. This TableContent is under the Panier folder.
I can't figure out what is wrong with the URL.
Does the TableContent should be under this folder ViewModels instead since it is using this model
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel?
Thanks
TableContent.cshtml (partial view) from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Table Content";
}
<a href="#" class="TableContent">
<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", "Produit", new { id =
item.ProduitId }, null)
</td>
<td>
#item.Produit.Prix
</td>
<td id="item-count-#item.PanierId">
#item.Quantite
</td>
<td>
<a href="#" class="RemoveLink" data-id="#item.PanierId"> Enlever du panier
</a>
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
</a>
Index.cshtml from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('.RemoveLink').click(function () {
$.ajax({
url: '/Panier/RemoveFromCart',
data: { id: $(this).data('id') },
type: 'POST',
cache: false,
success: function (result) {
$('#row-' + result.DeleteId).remove();
$('#row-' + result.DeleteId).fadeOut('slow');
$('#cart-status').text('Cart (' + result.CartCount + ')');
$('#update-message').text(result.Message);
$('#cart-total').text(result.CartTotal);
$.get("/Panier/TableContent").done(function (data) { <==error 404
$("#TableContent").html(data); });
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
}
});
return false;
});
});
</script>
<h3>
<em>Details</em> du panier:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<div id="table-content">
#Html.Partial("TableContent") <=== partial view call
</div>
PanierController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tp1WebStore3.Models;
using Tp1WebStore3.ViewModels;
namespace Tp1WebStore3.Controllers
{
public class PanierController : Controller
{
//
// GET: /Panier/
Tp1WebStoreDBEntities dbProduit = new Tp1WebStoreDBEntities();
//
// GET: /ShoppingCart/
public ActionResult Index()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
// Set up our ViewModel
var viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal()
};
// Return the view
return View(viewModel);
}
//
// GET: /Store/AddToCart/5
public ActionResult AddToCart(int id)
{
// Retrieve the album from the database
var addedProduit = dbProduit.Produits
.Single(produit => produit.ProduitId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduit);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
//
// 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 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 Json(results);
/* return View("CartSummary"); */
}
//
// GET: /ShoppingCart/CartSummary
[ChildActionOnly]
public ActionResult CartSummary()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
ViewData["CartCount"] = cart.GetCount();
return PartialView("CartSummary");
}
}
}
You'll want to keep your partial view inside the view folder (not view models)... the specific subdirectory is up to you but I believe it will default to looking in shared.
I'd suggest specifying more of the URL when you call the partial view and see if that fixes your issue...
For Example:
Html.Partial("~/Views/Shared/TableContent.cshtml")
More Info Here:
Render partial from different folder (not shared)
Ok I realize I misunderstood the question and the 404 was being generated by the script call not the #Html.Partial at the bottom of the file.
I'm going by this snippet from the comments...
$.get("~/Views/Shared/TableContent").done(function (data) { $("#TableContent").html(data); });
I see two issues here... First is that you are going to want to resolve your path differently as the "~" operator isn't going to help in javascript. You can use #url.Action("TableContent") in this case to get the actual url on the server and pass it in to your get statement.
The second issue is that I believe TableContent is just a view without a corresponding action. This is fine for rendering inline with a Html.Partial, however the server isn't going to be able to render it outside of that context. You'll want to add a corresponding action and call that instead from your ajax.
Your controller, Panier, doesn't seem to have a method called TableContent which should return the partial view TableContent.cshtml.
Also, when you refer the urls, try to use the Url.Action in the ajax / get calls:
url: '/Panier/RemoveFromCart',
Should be:
url: '#Url.Action("RemoveFromCart","Panier")',
Another way of solving this is to create an action TableContent in the Panier Controller which would call the partial view TableContent. The TableContent.cshtml should be in the same directory as Index (ie /Views/Panier)
public PartialViewResult TableContent()
{
return PartialView("TableContent");
}
You'll then need to replace a line in the ajax call
$.get("/Panier/TableContent")
becomes
$.get('#Url.Action("TableContent", "Panier")')

Categories

Resources