ASP.NET MVC 3 NOT showing appropriate view, action called using jquery - c#

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.

Related

ASP.NET MVC - Open Table in new window and print

I'm using ASP.NET MVC and have a table with 9 columns which shows results from the database where the user can filter values based on columns. The table structure looks like this:
<table class="tableMain" id="x">
<thead>
<tr class="trMain">
<th class="thMain">
#Html.DisplayNameFor(model => model.ID)
</th>
<th class="thMain">
#Html.DisplayNameFor(model => model.YEAR)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr class="trMain">
<td class="tdMain">
#Html.DisplayFor(modelItem => item.ID)
</td>
<td class="tdMain">
#Html.DisplayFor(modelItem => item.YEAR)
</td>
<td class="tdMain">
<input type="checkbox" class="chkCheckBoxId" name="airlineId" value="#item.ID" />
</td>
<td class="tdMain">
#Html.ActionLink("EditValue", "Edit", new { id = item.ID })
</td>
</tr>
}
</tbody>
</table>
Now I need a button, so that the dynamically generated table opens in a new window and the print dialog opens automatically. I had this piece of code:
<div class="line-btn">
<input type="submit" value="print" onclick="printTable()" class="btn fl btn-print">
</div>
<script language="javascript">
function printTable()
{
var printContent = document.getElementById("x");
var windowUrl = 'about:blank';
var num;
var uniqueName = new Date();
var windowName = 'Print' + uniqueName.getTime();var printWindow = window.open(num, windowName, 'left=50000,top=50000,width=0,height=0');
printWindow.document.write(printContent.innerHTML);
printWindow.document.close();
printWindow.focus();
printWindow.print();
printWindow.close();
}
</script>
The problem here is that the table is completely unsorted when printed so the rows/columns are shifted.
I found this example:
https://datatables.net/extensions/buttons/examples/print/simple.html
This is exactly what I need (open the table in a new window and open print dialog). But unfortunately this sample has a lot of code in the javascript files that I don't need. There is a search field included and a pagination.
Can someone help me please? Thank you very much!
Ok I found a good solution.
This is the code I used:
<script src="#Url.Content("~/Scripts/jquery-3.5.1.js")" type="text/javascript"></script>
<script>
var myApp;
myApp = (function (app) {
$('#x').click(function () {
myApp.print();
});
app.print = function () {
$.ajax({
url: 'Home/Print',
success: function (data) {
if (myApp.arePopupsBlocked()) {
alert('please allow popups.');
}
var printWindow = window.open();
if (printWindow) {
$(printWindow.document.body).html(data);
} else {
alert('please allow popups.');
}
},
error: function () {
alert('Error');
}
});
};
app.arePopupsBlocked = function () {
var aWindow = window.open(null, "", "width=1,height=1");
try {
aWindow.close();
return false;
} catch (e) {
return true;
}
};
return app;
})(window.myApp || {})
</script>
and right before the table-tag the link to click:
<style>
/* suppress link for printing */
##media only print {
a {
display: none;
}
}
</style>
[print table]
There opens no new window but the table is well formated for printing.

MVC 5 WEB API post

I am following this tutorial: https://www.codeproject.com/Articles/424461/Implementing-Consuming-ASP-NET-WEB-API-from-JQuery
to help me implement my web API. But I have something different. This is my index:
#model IEnumerable<dsr_vaja1.Models.Kosarica.Kosarica>
#{
ViewBag.Title = "kosarica";
Layout = "~/Views/Shared/MasterStran.cshtml";
}
<div id="accordion">
<h3>Igre</h3>
<div>
<table class="table table-hover ">
<tr>
<th>
#Html.DisplayNameFor(model => model.ime_igre)
</th>
<th>
#Html.DisplayNameFor(model => model.cena_igre)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ime_igre)
</td>
<td>
#Html.DisplayFor(modelItem => item.cena_igre)
</td>
</tr>
}
</table>
<button onclick="AddEmployee();return false;">Add Employee</button>
</div>
</div>
As you can see, here I have a LIST of items named Kosarica. This is my web api:
public void Post(Nakup nakup)
{
nakup.Id = 1;
nc.Nakupi.Add(nakup);
nc.SaveChanges();
}
My web api and everything works completely fine, now I would just like to know how I would use this function:
function AddGame() {
jQuery.support.cors = true;
var game = {
ID: model.id,
ime_igre: model.ime_igre,
};
$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI',
type: 'POST',
data:JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
FOR ALL of the items in the list after the user clicks a button.
**edit
Isn't there a simpler way to do this? I just realized that the first line of code is a list
#model IEnumerable
model is a list of objects. As you can see below in the foreach loop, I loop through the items in model. So can I just pass the model to the jquery function somehow?
Create a javascript function, eg :
function AddGamesForAllItems(){
// Select the table through JQuery Selector Here
//loop through the elements of the table Here
//Call the AddGame function passing by paremeters the needed elements from the table... You have to declare parameters inside you AddGame function
}
Call the AddGamesForAllItems function when you need it eg: Button click event.
Hope it could help !

Selection in the Controller is not matching

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.

How can I filter a list with a dropdown list

I am new to MVC, and I want on my view two things:
1 - A list of data's (3 columns)
2 - A dropdown list that I can filter the list (filled with data from the first column)
in my controller I have the following function:
public ViewResult ListUrl()
{
var ws = new Service1();
localhost.Service1 s1 = new Service1(); // data from web services
localhost.UrlInfo[] ui = s1.GetUrlInfo();
for (int i = 0; i < ui.Length; i++)
{
var UrlItem = new UrlItem();
UrlItem.Id = Convert.ToInt32(ui[i].Id);
UrlItem.urlll = ui[i].url;
UrlItem.toontijd = ui[i].ToonTijd;
UrlItem.positie = Convert.ToInt32(ui[i].positie);
Models.ListUrl.UrlList.Add(UrlItem);
}
var urlname = from url in s1.GetUrlInfo() select url ;
ViewData["url"] = new SelectList(urlname, "Id", "url");
return View();
}
In the view :
<script type="text/javascript">
$(document).ready(function () {
// How can I filter the list (see <table> tag) when I change index of dropdown list???
});
</script>
#Html.DropDownList("SelectedItem", (SelectList)ViewData["url"], "----- all ------", new { id = "0", text = "----- all ------" })
<table>
<tr>
<th>
Url
</th>
<th>
Toontijd
</th>
<th>
Positie
</th>
</tr>
#foreach (var item in ListUrl.UrlList)
{
<tr>
<td>
#item.urlll.ToString()
</td>
<td>
#item.toontijd.ToString()
</td>
<td>
</td>
<td>
#item.positie.ToString()
</td>
</tr>
}
How to get dropdownlist change event working?
Thanks a lot.
Hicham.
Well.. You need to do some stuff for this.. Let me explain in steps..
Create a partial view for the grid
Attach onchange event for dropdown
Make one controller action method which take dropdown selection as parameter and returns the grid partial view as result
$.get('yourActionURL', { parameter: $('#yourDropdownId').val() }, function(result) {
$('#grid').html(result);
});
Filtering a WebGrid with a DropDownList in MVC4 and ASP.NET MVC Filtering results in a list/grid - these link can help you in details about this.

Trying to understand HttpPost in MVC3 [duplicate]

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.

Categories

Resources