My Goal is to make a CreatePartialCategoryView within an index View. View loads just fine, bet there is just one small problem:
The CreatePartialView html elements are placed above the Index View's html elements. It looks like this at the moment:
Here's the code for the index view:
#model IEnumerable<GUI.Models.CategoryViewModel>
#Html.Partial("~/Views/Category/CreatePartial.cshtml",new GUI.Models.CategoryViewModel());
#{
ViewBag.Title = "Categories";
}
<h2>Categories</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
Here's the code of the CreatePartialView:
#model GUI.Models.CategoryViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Create a new Category</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And this is the code for the CategoryController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BLL;
using ClassLibrary.Entities;
using DAL;
using GUI.Models;
namespace GUI.Controllers
{
public class CategoryController : Controller
{
private readonly IRepository<Category> _repository;
private CategoryHandler _categoryHandler;
public CategoryController() : this(new Repository<Category>())
{
}
public CategoryController(IRepository<Category> repository)
{
_repository = repository;
_categoryHandler = new CategoryHandler(repository);
}
//
// GET: /Category/
public ActionResult Index()
{
var categories = _categoryHandler.GetAllCategories();
var categoryViewModels = new List<CategoryViewModel>();
foreach (Category category in categories)
{
var viewModel = new CategoryViewModel();
viewModel.Id = category.Id;
viewModel.Name = category.Name;
categoryViewModels.Add(viewModel);
}
//return View();
return View(categoryViewModels);
}
//
// GET: /Category/Details/5
public ActionResult Details(Guid id)
{
return View();
}
//
// GET: /Category/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Category/Create
[HttpPost]
public ActionResult Create(CategoryViewModel model)
{
try
{
// TODO: Add insert logic here
string categoryName = model.Name;
_categoryHandler.AddNewCategory(categoryName);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Category/Edit/5
public ActionResult Edit(Guid id)
{
return View();
}
//
// POST: /Category/Edit/5
[HttpPost]
public ActionResult Edit(Guid id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Category/Delete/5
public ActionResult Delete(Guid id)
{
return View();
}
//
// POST: /Category/Delete/5
[HttpPost]
public ActionResult Delete(Guid id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
So, how do I place the CreatePartialView html elements (Create form) below the index View elements (the list)?
Why don't you just put the line:
#Html.Partial("~/Views/Category/CreatePartial.cshtml",new GUI.Models.CategoryViewModel());
Just below your table listing the categories? like :
<table class="table">
...
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
#Html.Partial("~/Views/Category/CreatePartial.cshtml",new GUI.Models.CategoryViewModel());
Perhaps I'm misunderstanding you, but don't you just need to move #Html.Partial call below your list in your view?
#model IEnumerable<GUI.Models.CategoryViewModel>
#{
ViewBag.Title = "Categories";
}
<h2>Categories</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
#Html.Partial("~/Views/Category/CreatePartial.cshtml",new GUI.Models.CategoryViewModel());
Related
I get an error when loading a particular view via an Html.action call to an action and Controller, into a jquery Tab.
The other View is loaded successfully via an HTML.Partial call.
How do I get this other particular partial loaded please.
The tab where the error happens is tab4.
The commented out HTML.Partial call works to a point but when it loads that Partial (User), which has multiple models in it's containing model,..those other models are null and it's iteration over them crashes.
(That partial is beneath the first block of code.)
If I try load it from an action Call, then
the JQuery function ("$#tabs").tabs crashes with ".tabs" is undefined
TIA
Code:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Tabs - Content via Ajax</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function ()
{
$("#tabs").tabs({
beforeLoad: function (event, ui)
{
ui.jqXHR.fail(function ()
{
ui.panel.html(
"Couldn't load this tab. We'll try to fix this as soon as possible. " +
"If this wouldn't be a demo.");
});
}
});
});
</script>
<div id="tabs">
<ul>
<li>Person Detail</li>
<li>Addresses</li>
<li>Role Detail</li>
<li>User Detail</li>
</ul>
<div id="tabs-1">
#*#Html.Partial("~/Views/Person/Index.cshtml")*#
</div>
<div id="tabs-2">
#*#Html.Partial("~/Views/Address/Index.cshtml")*#
</div>
<div id="tabs-3">
#Html.Partial("~/Views/IdentityRole/List.cshtml", new List<Catalyst.Shared.IdentityRole>())
</div>
<div id="tabs-4">
#Html.Action("List", "User");
#*#Html.Partial("~/Views/User/List.cshtml", new Catalyst.Mvc.IdentityUserPersonViewModel())*#
</div>
</div>
The Partial which I want to load, but needs data, which I think would work if I called the Action as opposed to calling the Partial.
#model Catalyst.Mvc.IdentityUserPersonViewModel
#{
ViewBag.User = "List";
}
<div class="panel panel-default" style="width:1400px !important;text-align:center ">
<div class="panel-heading">
<h3>Users</h3>
</div>
<div class="panel-body">
<div style="text-align:right;">#Html.ActionLink("Add", "Create", null, new { #class = "btn btn-default" })</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
UserName
</th>
<th>
Password
</th>
<th>
Title
#*#Html.DisplayNameFor(model => model.)*#
</th>
<th>
FirstName
#*#Html.DisplayNameFor(model => model.)*#
</th>
<th>
LastName
</th>
<th>
PhoneNumber
</th>
<th>
Email
</th>
<th>
Company and Branch
</th>
<th></th>
<th></th>
</tr>
</thead>
#for (var i = 0; i < Model.identityUsers.Count(); i++)
{
<tr>
<td>
<a href="#Url.Action("Edit", "User" , new {id=Model.UserPersons[i].UserPersonId})">
#Html.DisplayFor(x => Model.identityUsers[i].UserName)
</a>
</td>
<td>
<a href="#Url.Action("Edit", "User" , new {id=Model.UserPersons[i].UserPersonId})">
#Html.EditorFor(x => Model.identityUsers[i].PasswordHash, new { htmlAttributes = new { #class = "form-control", placeholder = "Password", Type = "password" } })
</a>
</td>
<td>
<a href="#Url.Action("Edit", "User" , new {id=Model.UserPersons[i].UserPersonId})">
#Html.DisplayFor(x => Model.UserPersons[i].Title)
</a>
</td>
<td>
<a href="#Url.Action("Edit", "User" , new {id=Model.UserPersons[i].UserPersonId})">
#Html.DisplayFor(x => Model.UserPersons[i].Name)
</a>
</td>
<td>
<a href="#Url.Action("Edit", "User" , new {id=Model.UserPersons[i].UserPersonId})">
#Html.DisplayFor(x => Model.UserPersons[i].Surname)
</a>
<td>
#*<a href="#Url.Action("Edit", "User" , new {id=Model.identityUsers[i].Id})">
#Html.DisplayFor(x => Model.identityUsers[i].Email)
</a>*#
</td>
<td>
#*<a href="#Url.Action("Edit", "User" , new {id=Model.identityUsers[i].Id})">
#Html.DisplayFor(x => Model.identityUsers[i].PhoneNumber)
</a>*#
</td>
<td>
#*<a href="#Url.Action("Edit", "User" , new {id=item.ID})">
#Html.DisplayFor(x => item.PhoneNumber)
</a>*#
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id =
Model.identityUsers[i].Id })
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { id =
Model.identityUsers[i].Id })
</td>
</tr>
}
</table>
</div>
The Controller of the view I can't get laoded
public class UserController : Controller
{
private IdentityUserBo identityUserBo;
private PersonBo personBo;
private IdentityUserPersonBo identityuser_personBo;
IdentityUserPersonViewModel model = new IdentityUserPersonViewModel();
public UserController(IdentityUserBo boIdentityUser, PersonBo boPerson, IdentityUserPersonBo boIdentityUserPerson )
{
this.identityUserBo = boIdentityUser ?? throw new ArgumentNullException("boIdentityUser");
this.personBo = boPerson ?? throw new ArgumentNullException("boPerson");
this.identityuser_personBo = boIdentityUserPerson ?? throw new ArgumentNullException("boIdentityUserPerson");
}
public ActionResult Index()
{
return RedirectToAction("List");
}
public ActionResult List()
{
ExBool result = null;
IdentityUserPersonViewModel userPersonViewModel = new IdentityUserPersonViewModel();
result = this.identityUserBo.List(out List<IdentityUser> identityUsers);
if (!result.Success) throw new Exception(result.Messages);
if (identityUsers == null) throw new Exception("Could not load IdentityUsers");
// Ideally see detail eg branch and tel and email from their respective tables
userPersonViewModel.identityUsers = identityUsers;
//Get the Persons, match these via Person.Id -> IdentityUserPerson.FKPersonId + IdentityUserPerson.FKUserId -> IdentityUser.ID
List<Person> persons = null;
result = this.personBo.List(out persons);
//IdentityUserPersonViewModel viewModel = new IdentityUserPersonViewModel();
userPersonViewModel.persons = persons;
// Get the IdentityUserPersons
List<IdentityUserPerson> identityUserPersons = null;
result = this.identityuser_personBo.List(out identityUserPersons);
IdentityUserPerson UPRec = new IdentityUserPerson();
Person PRec = new Person();
userPersonViewModel.UserPersons = new List<UserPerson>();
foreach (IdentityUser rec in userPersonViewModel.identityUsers)
{
UPRec = identityUserPersons.Find(x => x.FKUserID == rec.Id);
if (UPRec != null)
{
//UserId, UserPersonId, + Person.Id + Person.Name + Person.Surname
PRec = persons.Find(y => y.ID == UPRec.FKPersonID);
UserPerson UsrPers = new UserPerson();
UsrPers.UserId = rec.Id;
UsrPers.UserPerson_FKPersonId = UPRec.FKPersonID;
UsrPers.UserPerson_FKUserId = UPRec.FKUserID;
UsrPers.Name = PRec.FirstName;
UsrPers.Surname = PRec.LastName;
UsrPers.Title = PRec.TitleCode;
userPersonViewModel.UserPersons.Add(UsrPers);
}
else
{
UserPerson UsrPers = new UserPerson();
userPersonViewModel.UserPersons.Add(UsrPers);
}
}
return View(userPersonViewModel);
}
Check your console what error you got.
and also change this in tab4
#{
#Html.Partial("List", new Catalyst.Mvc.IdentityUserPersonViewModel())
}
I'm new to mvc and am trying to figure out how to create an approve button on an index view. Some clarification is needed.
There is a question here already about creating an Approve/Unapprove button in an mvc view. But after reviewing it, it appears to be missing information. The controller is expecting the SubmitButton and the ID to be passed to it. This I understand. But the view's submit buttons only sends the SubmitButton with no ID. Can someone please clear the fog? Thank you.
Controller
[ActionName("Index")]
[HttpPost]
public ActionResult IndexPost(string SubmitButton, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string buttonClicked = SubmitButton;
if(buttonClicked == "Approve")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "APPROVED";
db.SaveChanges();
}
else if(buttonClicked == "Unapprove")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "UNAPPROVED";
db.SaveChanges();
}
//Save Record and Redirect
return RedirectToAction("Index");
}
View
<button type="submit" name="SubmitButton" value="Approve" class="btn btn-sm btn-success">Approve</button>
<button type="submit" name="SubmitButton" value="Unapprove" class="btn btn-sm btn-danger">Unapprove</button>
The controller will them update the database with the status change and return the Index to reflect the changes.
According to your newest example, here is the best answer I can think. At first, your code example has a few syntax errors and I needed to create own macaddress -class. I hope its similar than yours.
I used the same example than in my earlier answer. I only modified view and created maccaddress -class. The controller is same as earlier.
Modified View
This is the important part. I think you just have formatted Html form and tables in weird way. Here is a screenshot of how the view is rendered.
Now when user click Approve or Unapprove the form will send maccaddress id and button value to the controller IndexPost -action.
In a view example:
table is made just for example, modify it if needed.
I changed foreach location, now it is before Html.BeginForm. In your example, BeginForm was outside foreach and that caused a few problems when submitting your code. In a way how your form was rendered, it was impossible to know which Id is submitted.
Look #Html.Hidden("id", item.idMACAddress). It should be inside BeginForm.
I have only print id and status into a table for example purposes.
Action buttons are in the third column.
So why it works now is the way Form is rendered. In the example, there is now one html form for every maccaddress row. When a button is clicked, we know exactly what values we want to send into the controller.
#model IEnumerable<MySQL_MACAddress.Models.macaddress>
#{ ViewBag.Title = "Index"; }
<table class="table">
<tr>
<th> MAC Address </th>
<th> Status </th>
<th> Actions </th>
</tr>
#foreach (var item in Model)
{
using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.Hidden("id", item.idMACAddress)
<tr>
<td> #item.idMACAddress </td>
<td> #item.Status </td>
<td>
<button type="submit" name="SubmitButton" value="Approve" class="btn btn-sm btn-success">Approve</button>
<button type="submit" name="SubmitButton" value="Unapprove" class="btn btn-sm btn-danger">Unapprove</button>
</td>
</tr>
}
}
</table>
maccaddress.cs example
Check this example. Don't just copy it because probably it won't work with your code. The view is a more important part here so look it.
using System;
namespace MySQL_MACAddress.Models
{
public class macaddress
{
public macaddress()
{
}
public string Status { get; set; }
public int idMACAddress { get; set; }
}
}
Controller
Check earlier answer.
I suppose you have an HTML form in View made with Html-helpers. In your case, the following example code is probably the simplest one.
View - Home/Index.cshtml
<h2>Welcome to ASP.NET MVC!</h2>
<!--
If needed, check BeginForm parameters to send POST
into right controller and action.
-->
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<!-- second parameter is the value for id field. -->
#Html.Hidden("id", 2001)
<button type="submit" name="SubmitButton" value="Approve" class="btn btn-sm btn-success">Approve</button>
<button type="submit" name="SubmitButton" value="Unapprove" class="btn btn-sm btn-danger">Unapprove</button>
}
Controller - HomeController.cs
using System.Net;
using System.Web.Mvc;
namespace FormTest.Controllers
{
public class HomeController : Controller
{
// GET action for index
public ActionResult Index()
{
// Do something here ...
return View();
}
// POST action for index.
// Will use same path as GET
[HttpPost]
[ActionName("Index")]
public ActionResult IndexPost(string SubmitButton, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (SubmitButton == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//Redirect to GET Index
return RedirectToAction("Index");
}
}
}
The important part is the Hidden helper that will generate a hidden input field. If you need more modifications in your use case, read more here about parameters and examples.
#T.Nylund , Your thoughts? Thank you.
View
#model Enumerable<MySQL_MACAddress.Models.macaddress>
#{ ViewBag.Title = "Index"; }
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Status)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#HtmlHidden("id", item.idMACAddress)
</td>
<td>
#Html.DisplayFor(modelitem => item.Status)
</td>
<button type="submit" name="SubmitButton" value="Approve" class="btn btn-sm btn-success">Approve</button>
<button type="submit" name="SubmitButton" value="Unapprove" class="btn btn-sm btn-danger">Unapprove</button>
}
We use different controller methods for the different actions when approving (button to approve, button to reject)
Our view:
if (!Model.IsApproved)
{
<td>
#using (Html.BeginForm("Approve", "BudgetItem", new { id = Model.BudgetItemSid, role = Model.ActiveRole }, FormMethod.Post))
{<button type="submit" id="btnApprove" style="display: none;">Approve</button>}
</td>
}
if (!Model.IsRejected)
{
<td>
#using (Html.BeginForm("Reject", "BudgetItem", new { id = Model.BudgetItemSid, role = Model.ActiveRole }, FormMethod.Post))
{<button type="submit" id="btnReject" style="display: none;">Reject</button>}
</td>
}
Our Controller:
[HttpPost]
public ActionResult Approve(int id, EnumRole role)
{
}
[HttpPost]
public ActionResult Reject(int id, EnumRole role)
{
}
I know I've asked a lot of questions lately and for that I apologize, I'm in the process of learning the ins and outs of MVC. Anyways, when I select a quantity and hit add to cart it doesn't add the quantity I select, almost like it just grabs a random number and adds it. Here's the code for the view:
#model IEnumerable<AccessorizeForLess.ViewModels.DisplayProductsViewModel>
#{
ViewBag.Title = "Products > Necklaces";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="~/Content/Site.css" rel="stylesheet" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/jquery.fancybox.css?v=2.1.5" rel="stylesheet" />
<link href="~/Content/jquery.fancybox-buttons.css?v=1.0.5" rel="stylesheet" />
<link href="~/Content/jquery.fancybox-thumbs.css?v=1.0.7" rel="stylesheet" />
<h2>Products > Necklaces</h2>
<div id="update-message"></div>
<p class="button">
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm("AddToCart", "Orders", FormMethod.Post))
{
<div id="container">
<div class="scroll">
#foreach (var item in Model)
{
<div class="scroll">
<div class="itemcontainer">
<table>
<tr>
<td id="#item.Id">
<div class="DetailsLink"> #Html.ActionLink(#item.Name, "Details", new { id = item.Id })</div>
<br />
<div id="#item.Id"></div>
<div class="divPrice" id="#item.Price">#Html.DisplayFor(modelItem => item.Price)</div>
<div class="divImg"><a class="fancybox-thumbs" href="#item.Image.ImagePath" title="#item.Image.AltText" data-fancybox-group="thumb"><img src="#item.Image.ImagePath" alt="#item.Image.AltText" title="#item.Image.AltText" /></a></div>
<div> </div>
<div class="divQuantity"> Quantity: #Html.TextBoxFor(modelItem => item.Quantity, new { #id = "quantity", #style = "width:50px;", #class = "formTextBox" })</div>
<div class="divAddToCart">
<p class="button">
#Html.ActionLink("Add to cart", "AddToCart", "Orders", new { id = item.Id }, new { #class = "AddToCart" })
</p>
</div>
<div style="height:15px;"></div>
</td>
</tr>
</table>
</div>
</div>
}
<div class="button">#Html.ActionLink("Back To Categories","Categories")</div>
<br />
</div>
</div>
}
#section scripts {
<script src="~/Scripts/jQuery-jScroll.js"></script>
<script src="~/Scripts/jquery.fancybox.js?v=2.1.5"></script>
<script src="~/Scripts/jquery.fancybox-thumbs.js?v=1.0.7"></script>
<script src="~/Scripts/jquery.fancybox-buttons.js?v=1.0.5"></script>
<script type="text/javascript">
//$(function () {
// $('.scroll').jscroll({
// autoTrigger: true
// });
$('.fancybox-thumbs').fancybox({
prevEffect: 'none',
nextEffect: 'none',
closeBtn: true,
arrows: false,
nextClick: false
});
});
</script>
}
Here's the code for AddToCart in my controller:
// GET: /Orders/AddToCart/5
public ActionResult AddToCart(int id)
{
// Retrieve the product from the database
var productAdded = db.Products
.Single(p => p.ProductId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(productAdded);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
And finally the code for AddToCart in my ShoppingCart model:
public void AddToCart(Product item)
{
// Get the matching cart and product instances
var order = entities.Orders.FirstOrDefault(
c => c.OrderGUID == ShoppingCartId
&& c.OrderItems.Where(p=>p.ProductId == item.ProductId).FirstOrDefault().ProductId == item.ProductId);
if (order == null)
{
// Create a new order since one doesn't already exist
order = new Order
{
InvoiceNumber = Guid.NewGuid().ToString(),
OrderDate=DateTime.Now,
OrderGUID = ShoppingCartId,
IsShipped = false
};
entities.Orders.Add(order);
// Save changes
entities.SaveChanges();
//add the OrderItem for the new order
OrderItem oi = new OrderItem()
{
OrderId = order.OrderId,
OrderGUID = ShoppingCartId,
ProductId = item.ProductId,
ProductQuantity = item.Quantity,
ProductPrice = item.ProductPrice
};
entities.OrderItems.Add(oi);
entities.SaveChanges();
}
else
{
// If the item does exist in the cart,
// then add one to the quantity
order.OrderItems.Where(p => p.ProductId == item.ProductId).FirstOrDefault().ProductQuantity++;
entities.SaveChanges();
}
}
Code for DisplayProductsViewModel:
using AccessorizeForLess.Data;
using System.ComponentModel.DataAnnotations;
namespace AccessorizeForLess.ViewModels
{
public class DisplayProductsViewModel
{
public int Id { get; set; }
public string Name { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
public decimal? Price { get; set; }
public ProductImage Image { get; set; }
public int ProductQuantity { get; set; }
}
}
Can anyone possibly see what I'm doing wrong
EDIT
This is what I see when I use the debugging tools
EDIT
'Here is the new view with the submit button added
#model IEnumerable<AccessorizeForLess.ViewModels.DisplayProductsViewModel>
#{
ViewBag.Title = "Products > Necklaces";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="~/Content/Site.css" rel="stylesheet" />
<link href="~/Content/jquery.fancybox.css?v=2.1.5" rel="stylesheet" />
<link href="~/Content/jquery.fancybox-buttons.css?v=1.0.5" rel="stylesheet" />
<link href="~/Content/jquery.fancybox-thumbs.css?v=1.0.7" rel="stylesheet" />
<h2>Products > Necklaces</h2>
<div id="update-message"></div>
<p class="button">
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm("AddToCart", "Orders", FormMethod.Post))
{
<div id="container">
<div class="scroll">
#foreach (var item in Model)
{
<div class="scroll2">
<div class="itemcontainer">
<table>
<tr>
<td id="#item.Id">
<div class="DetailsLink"> #Html.ActionLink(#item.Name, "Details", new { id = item.Id })</div>
<br />
<div id="#item.Id"></div>
<div class="divPrice" id="#item.Price">#Html.DisplayFor(modelItem => item.Price)</div>
<div class="divImg"><a class="fancybox-thumbs" href="#item.Image.ImagePath" title="#item.Image.AltText" data-fancybox-group="thumb"><img src="#item.Image.ImagePath" alt="#item.Image.AltText" title="#item.Image.AltText" /></a></div>
<div> </div>
<div class="divQuantity"> Quantity: #Html.TextBoxFor(modelItem => item.Quantity, new { #id = "quantity", #style = "width:50px;", #class = "formTextBox" })</div>
<div class="divAddToCart">
<input type="submit" value="Add To Cart" class="btn btn-default" /> #*#Html.ActionLink("Add to cart", "AddToCart", "Orders", new { id = item.Id }, new { #class = "AddToCart" })*#
</div>
<div style="height:15px;"></div>
</td>
</tr>
</table>
</div>
</div>
}
<div class="button">#Html.ActionLink("Back To Categories","Categories")</div>
<br />
</div>
</div>
}
#section scripts {
<script src="~/Scripts/jQuery-jScroll.js"></script>
<script src="~/Scripts/jquery.fancybox.js?v=2.1.5"></script>
<script src="~/Scripts/jquery.fancybox-thumbs.js?v=1.0.7"></script>
<script src="~/Scripts/jquery.fancybox-buttons.js?v=1.0.5"></script>
<script type="text/javascript">
//$(function () {
// $('.scroll').jscroll({
// autoTrigger: true
// });
$('.fancybox-thumbs').fancybox({
prevEffect: 'none',
nextEffect: 'none',
closeBtn: true,
arrows: false,
nextClick: false
});
// Document.ready -> link up remove event handler
//$(".AddToCart").click(function () {
// alert('Clicked!');
//});
//s});
</script>
}
And AddToCart
[HttpPost]
public ActionResult AddToCart(DisplayProductDetailsViewModel model)
{
// Retrieve the product from the database
var productAdded = db.Products
.Single(p => p.ProductId == model.Id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(productAdded);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
When I set a breakpoint in AddToCart model is always null, what am I missing here?
You are always sending the same quantity because you always trigger the ActionLink's GET request that only passes the query string parameter id. The quantity field in your form is never sent as that's part of the POST form body submission.
// you are not triggering this submission: POST AddToCart
#using(Html.BeginForm("AddToCart", "Orders", FormMethod.Post))
{
// quantity is passed on the request's body
#Html.TextBoxFor(modelItem => item.Quantity)
// but GET AddToCart/id is send instead
#Html.ActionLink("Add to cart", "AddToCart", "Orders", new { id = item.Id }, new { #class = "AddToCart" })
}
As indicated by your screenshot
Request URL: http://localhost:24177/Orders/AddToCart/21
Request Method: GET
Status Code: 302 Found
Notice "Form Data" or "Request Body" is missing from your request.
Each time you call GET AddToCart you query the same product from the data store and set the quantity property to the same value.
You ought to send this GET request as POST instead because:
It can be cached by the browser and it won't make subsequent requests to the
server
Web crawlers can trigger the ActionLink request
So add a submit button to your form and make a POST action. Then be sure the assign a new quantity from the form.
[HttpPost]
public ActionResult AddToCart(FormModel model)
{
var product = db.Products.Where(... && p => p.Id == model.ProductId);
var quantity = model.ProductQuantity;
cart.AddToCart(product, quantity);
return RedirectToAction("Index");
}
i have a form by dropdownlist element. i want get value of dropdownlist in controller.
i do not know how can do this. i read my username of users with dataview in controller and want to change role of them by dropdownlist options.
#using (Html.BeginForm()) {
<form name="register" action="#">
<div>
<table>
#foreach (MembershipUser user in Model)
{
var userroles = Roles.GetRolesForUser(user.UserName);
<tr>
<td>
#user.UserName
</td>
#foreach (var role in userroles)
{
<td>
#role
</td>
}
<td>
#Html.DropDownList("roleName")
#Html.ValidationMessage("roleName")
</td>
<td>
</td>
</tr>
}
</table>
<input type="submit" class="register" value="Save" />
</div>
</form>
}
and this is my controller:
public ActionResult Index()
{
ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName");
return View(Membership.GetAllUsers());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index()
{
return RedirectToAction("Index", "Home");
}
Did you try:
public ActionResult Index(string roleNameSelectedValue)
{
// roleNameSelectedValue is the "Value" field of selected item in your dropdownlist
return RedirectToAction("Index", "Home");
}
Or using #Html.DropDownListFor(m => Model.roleName, ViewBag.roleName as SelectList)
still now i generate html table like below code example but interested to know how could i generate html table using editorfor using editor template
see my full razor and view model code and guide me how to achieve my goal.
#model MVCCRUDPageList.Models.StudentListViewModel
#{
ViewBag.Title = "Index";
}
<h2>CREATE TABULAR UI WITH HTML TABLE</h2>
#using (Html.BeginForm("Index", "HtmlTable", FormMethod.Post))
{
<div class="form-group">
<div class="col-md-12 table-responsive">
<table class="table table-bordered table-hover">
<tr>
<th>
Row No
</th>
<th>
ID
</th>
<th>
Name
</th>
<th>
Country
</th>
<th>
Hobbies
</th>
<th>
Sex
</th>
</tr>
}
#for (int x=0; x<=Model.Students.Count-1;x++)
{
<tr>
<td>
<label>#(x+1)</label>
</td>
<td>
#Html.TextBoxFor(m => m.Students[x].ID)
</td>
<td>
#Html.TextBoxFor(m => m.Students[x].Name)
</td>
<td>
#Html.DropDownListFor(m => m.Students[x].CountryID,
new SelectList(Model.Country, "ID", "Name", Model.Students[x].CountryID),
"-- Select Countries--", new { id = "cboCountry", #class = "edit-mode" })
</td>
<td>
#for (var i = 0; i < Model.Students.FirstOrDefault().Hobbies.Count; i++)
{
<div class="checkbox">
#Html.HiddenFor(m => m.Students[x].Hobbies[i].ID)
#Html.HiddenFor(m => m.Students[x].Hobbies[i].Name)
#Html.CheckBoxFor(m => m.Students[x].Hobbies[i].Checked)
#Html.LabelFor(m => m.Students[x].Hobbies[i].Name, Model.Students[x].Hobbies[i].Name)
</div>
}
</td>
<td>
#for (var i = 0; i < Model.Sex.Count; i++)
{
<div class="checkbox">
#Html.HiddenFor(m => Model.Sex[i].ID)
#Html.HiddenFor(m => Model.Sex[i].SexName)
#Html.RadioButtonFor(m => m.Students[x].SexID, Model.Sex[i].ID)
#Html.LabelFor(m => m.Students[x].SexID, Model.Sex[i].SexName)
</div>
}
</td>
</tr>
}
</table>
</div>
<input type="submit" value="Submit" />
</div>
}
View Model Code
public class StudentListViewModel
{
public IList<Student> Students { get; set; }
public List<Country> Country { get; set; }
public List<Sex> Sex { get; set; }
public StudentListViewModel()
{
Students = new List<Student>
{
new Student
{
ID=1,Name="Keith",CountryID=0,SexID="F",
Hobbies= new List<Hobby>
{
new Hobby{ID=1,Name="Football",Checked=false},
new Hobby{ID=2,Name="Hocky",Checked=false},
new Hobby{ID=3,Name="Cricket",Checked=false}
}
},
new Student
{
ID=2,Name="Paul",CountryID=2,
Hobbies= new List<Hobby>
{
new Hobby{ID=1,Name="Football",Checked=false},
new Hobby{ID=2,Name="Hocky",Checked=false},
new Hobby{ID=3,Name="Cricket",Checked=false}
}
},
new Student
{
ID=3,Name="Sam",CountryID=3,
Hobbies= new List<Hobby>
{
new Hobby{ID=1,Name="Football",Checked=false},
new Hobby{ID=2,Name="Hocky",Checked=false},
new Hobby{ID=3,Name="Cricket",Checked=false}
}
}
};
Country = new List<Country>
{
new Country{ID=1,Name="India"},
new Country{ID=2,Name="UK"},
new Country{ID=3,Name="USA"}
};
Sex = new List<Sex>
{
new Sex{ID="M",SexName="Male"},
new Sex{ID="F",SexName="Female"}
};
}
}
please guide me how to restructure my razor code to use editorfor and editor template for clean code. what will be name of editor template ?
thanks
To use an EditorTemplate using #Html.EditorFor(m => m.SomeProperty) (where SomeProperty is a complex object, or collection of complex objects), then the template must be located in the /Views/Shared/EditorTemplates or /Views/YourControllerName/EditorTempates folder, and be named the same as the class name for SomeProperty.
In your case, if you want an EditorTemplate for typeof Student, then the template (a partial view) will be named Student.cshtml.
#model yourAssembly.Student
<tr>
<td>#Html.TextBoxFor(m => m.ID)</td>
<td>#Html.TextBoxFor(m => m.Name)<td>
....
<tr>
and in the main view, your would use
<table>
<thead> .... </thead>
<tbody>
#Html.EditorFor(m => m.Students)
</tbody>
</table>
which will generate the correct html for each item in your collection.
However, since you also have a dropdownlist for CountryID, then you need to pass the SelectList to the template (the template has no knowledge of the parent model) using additionalViewData, so the code needs to be modified to
#Html.EditorFor(m => m.Students, new { Countries = Model.Countries})
where the Countries property in StudentListViewModel should be
public IEnumerable<SelectListItem> Countries { get; set; }
and delete you current List<Country> Country property. Then in the view generate the dropdownlist using
<td>#Html.DropDownListFor(m => m.CountryID, (IEnumerable<SelectListItem>)ViewData["Countries "], "-- Select Country--", new { ... })<td>
Note you should not be adding new { id = "cboCountry" } because its creating invalid html (duplicate id attribute).
Now you can extend this further by creating an EditorTemplate for Hobby (which will be named Hobby.cshtml
#model yourAssembly.Hobby
<div class="checkbox">
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Name)
#Html.CheckBoxFor(m => m.Checked)
#Html.LabelFor(m => m.Checked, Model.Name)
</div>
Note the LabelFor() should be for the Checked property, not the Name property as you currently have it.
Then in your Student.cshtml template, use
<td>#Html.EditorFor(m => m.Hobbies)<td>
to generate the correct html for each Hobby.