Cart not adding correct quantity EF 6 MVC 5 - asp.net-mvc-5

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");
}

Related

Ajax in JavaScript is posting raw data into web page

When making an ajax request in JavaScript, it appears that the view has received a post of raw data into web page, i would say this is like looking at a csv file in notepad, just lines and lines of data, albeit the correct data, just not in the jquery datatable i would expect to see.
When just using Jquery to display all the data correctly in the table like so:
<script>
$('#IndexTable').DataTable({ responsive: true });
</script>
There is no issue.
I have also tried this in the view:
<script>
$(document).ready(function () {
test();
})
var test = function () {
$ajax({
type: 'GET',
url: '/ClinicalASSPATVM/test',
success: function (response) {
BindDataTable(response);
}
})
}
var BindDataTable = function (response) {
$("#IndexTable").DataTable({
"aadata": response,
"aoColumn": [
{"mData": "Product:"},
]
});
}
</script>
This is my Controller portion of the code:
public ActionResult test(int? ClinicalAssetID)
{
var ClinicalASSPATVM = (from s in db.ClinicalAssets
join cp in db.ClinicalPATs on s.ClinicalAssetID equals cp.ClinicalAssetID into AP
from subpat in AP.DefaultIfEmpty()
orderby s.ClinicalAssetID descending
select new ClinicalASSPATVM
{
ClinicalAssetID = s.ClinicalAssetID,
ProductName = s.ProductName,
ModelName = s.ModelName,
SupplierName = s.SupplierName,
ManufacturerName = s.ManufacturerName,
SerialNo = s.SerialNo,
PurchaseDate = s.PurchaseDate,
PoNo = s.PoNo,
Costing = s.Costing,
TeamName = s.TeamName,
StaffName = s.StaffName,
InspectionDocumnets = subpat.InspectionDocumnets ?? String.Empty,
InspectionOutcomeResult = subpat.InspectionOutcomeResult
});
return Json(new { data = ClinicalASSPATVM }, JsonRequestBehavior.AllowGet);
}
This is the View:
#model IEnumerable<Assets.Areas.Clinical.Models.ClinicalASSPATVM>
<link href="~/content/datatables/media/css/datatables.bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/DataTables/extensions/Responsive/css/responsive.dataTables.min.css" rel="stylesheet" />
#{
ViewBag.Title = "View Clinical";
}
<div class="pageheader">
<h2><i class="fa fa-pencil"></i> Clinical Asset Dashboard</h2>
<div class="breadcrumb-wrapper">
<span class="label">You are here:</span>
<ol class="breadcrumb">
<li>Asset Management System</li>
<li class="active">Clinical Assets - Overview</li>
</ol>
</div>
</div>
<div class="contentpanel">
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-btns">
−
</div><!-- panel-btns -->
<h3 class="panel-title">Last 10 Assets:</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<table id="IndexTable" class="table table-striped table-bordered" >
<thead>
<tr>
<th>Product:</th>
<th>Model:</th>
<th>Supplier:</th>
<th>Manufacturer:</th>
<th>Serial No:</th>
<th>Purchase Date:</th>
<th>Purchase Order No:</th>
<th>Cost:</th>
<th>Team Location:</th>
<th>Owner:</th>
<th>Inspection OutcomeResult:</th>
</tr>
</thead>
</table>
</div><!-- table-responsive -->
</div><!-- panel-body -->
</div><!-- panel -->
</div>
#section Scripts {
<script src="~/Scripts/DataTables/media/js/jquery.dataTables.min.js"></script>
<script src="~/Scripts/DataTables/media/js/dataTables.bootstrap.min.js"></script>
<script src="~/Scripts/DataTables/extensions/Responsive/js/dataTables.responsive.js"></script>
<script>
$(document).ready(function () {
$ajax({
url: '/ClinicalASSPATVM/test',
method: 'GET',
datatype: 'json',
sucess: function (data) {
$('#IndexTable').datatable({
data: data,
columns: [
{ "data": "ProductName" },
]
});
}
});
});
</script>
}
This is the crazy output example, also i see no layout page headers, footers or side bars.
{"data":
[{"ClinicalAssetID":75,"SerialNo":"34563463453453453","PurchaseDate":"\/Date(1551657600000)\/","PoNo":"567","Costing":1500,"InspectionDocumnets":"","ProductName":{"ProductID":2,"AssetAssignmentID":2,"ProductName":"Bed"},"InspectionOutcomeResult":null,"ModelName":{"ModelID":1,"AssetAssignmentID":2,"ProductID":8,"ModelName":"M1"},"Code":null,"AssetTypeName":null,"ManufacturerName":{"ManufacturerID":1,"AssetAssignmentID":2,"ProductID":8,"ManufacturerName":"Omron"},"StaffName":{"StaffID":1,"StaffName":
I Hope someone can shed some light on what i have done wrong.

redirect List<Data> to a view after user has submitting a form

I have a form where the user enter his/her details.
#using (Html.BeginForm("Create","Coupons"))
{
<div class="row">
<div class="col-sm-8">
<div class="page-header">Generer Coupon</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.Student)
#Html.DropDownListFor(m => m.Student, new SelectList(Model.Students, "Id", "Name"), "", new { #class = "form-control input-lg" })
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.Price)
#Html.TextBoxFor(m => m.Price, new { #class = "form-control input-lg" })
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.NumberOfCoupons)
#Html.TextBoxFor(m => m.NumberOfCoupons, new {#class = "form-control input-lg"})
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
<button class="btn btn-success btn-lg">Generer</button>
</div>
</div>
}
I redirect the view to the Create Method on CouponsController
[HttpPost]
public ActionResult Create(CouponViewModel viewModel)
{
if (!ModelState.IsValid)
{
var model = new CouponViewModel
{
Students = _context.Students.ToList()
};
return View("Index", model);
}
for (int i = 1; i <= viewModel.NumberOfCoupons; i++)
{
var coupon = new Coupon
{
CouponNumber = viewModel.CouponNumber,
ValidationCode = viewModel.ValidationCode(6),
Price = viewModel.Price,
StudentId = viewModel.Student,
DateTime = Convert.ToDateTime(DateTime.Now.ToString("yy-MMM-dd ddd"))
};
_context.Coupons.Add(coupon);
_context.SaveChanges();
}
var coupons = _context.Coupons
.Where(c => c.StudentId == viewModel.Student)
.Include(s => s.Student)
.ToList();
TempData["viewModel"] = coupons;
return RedirectToAction("GetCoupons");
}
here is the view i receive the tempdata to display on the view
[HttpPost]
public ActionResult GetCoupons()
{
Coupon coupon = TempData["viewModel"] as Coupon;
return View("Print", (IEnumerable<Coupon>)coupon);
}
I have been stucked for like 3 days. I don't know where im wrong
There are a couple of problems with your example. But you can eliminate them if you do some things differently.
[HttpPost]
public ActionResult Create(CouponViewModel viewModel)
{
return RedirectToAction("GetCoupons", new { studentId = viewModel.Student });
}
First, your redirected action needs to be marked [HttpGet]. You can also avoid TempData if you pass the id on the query string, then perform the lookup in the redirected action.
[HttpGet]
public ActionResult GetCoupons(int studentId)
{
var coupons = _context.Coupons
.Where(c => c.StudentId == studentId)
.Include(s => s.Student)
.ToList();
return View("Print", coupons);
}
TempData isn't wrong but it won't persist on a refresh. Sometimes you will pass sensitive data which makes it useful then. Your cast to a single Coupon isn't quite what you want -- Cast to a collection instead.
[HttpGet]
public ActionResult GetCoupons()
{
var coupons = TempData["viewModel"] as IEnumerable<Coupon>;
return View("Print", coupons);
}

Foundation 5 Abide validation not working with MVC5

I am trying to hook up Foundation 5 abide validation to my MVC 5 view.When I leave the required fields and try to submit the form,I see all the required fields highlighted in red,but I want to see the error message I added to the C# view model in the Required(ErrorMessage="username is required"]
These are the things I already added
Added these keys to my root level web.config
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Added the data_abide attribute to the form element
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { id = "form-user-register", data_abide = "" }))
{
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LoginName)<br />
#Html.TextBoxFor(m => m.LoginName, new { id = "register-loginname"})
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.UserPassword)<br />
#Html.TextBoxFor(m => m.UserPassword, new { id = "register-loginpassword" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.Email)<br />
#Html.TextBoxFor(m => m.Email, new { id = "register-loginpassword" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.FirstName)<br />
#Html.TextBoxFor(m => m.FirstName, new { id = "register-login-firstname" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LastName)<br />
#Html.TextBoxFor(m => m.FirstName, new { id = "register-login-firstname" })
</div>
</div>
<div class="row">
<div class="small-12 columns">
<div class="left">
<input type="submit" class="button radius small right" value="Register" />
</div>
</div>
</div>
}
I made sure that the jquery.validate.unobtrusive.js and jquery.validate.js is added to the _LayoutView.cshtml
This is the C# Viewmodel
public class RegisterViewModel
{
public int AppUserId { get; set; }
[Display(Name="Username")]
[Required(ErrorMessage="Username is required")]
public string LoginName { get; set; }
[Display(Name = "Email")]
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Display(Name = "FirstName")]
[Required(ErrorMessage = "FirstName is required")]
public string FirstName { get; set; }
[Display(Name = "LastName")]
[Required(ErrorMessage = "LastName is required")]
public string LastName { get; set; }
[Display(Name = "Password")]
[Required(ErrorMessage = "Password is required")]
public string UserPassword { get; set; }
public AddressViewModel Address { get; set; }
}
Still I only the the above screenshot
I figured out what the issue was.This might help someone like me in the future
I was missing couple of things in my _Layout.cshtml and the Register view
1.Missed thi sfrom _Layout view
<script>
$(document).foundation()
</script>
2.Forgot to add the required HTML5 attribute and the html tag that abide validation uses to display the model error
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LoginName)<br />
#Html.TextBoxFor(m => m.LoginName, new { id = "register-loginname" ,required=""})
<small class="error">Username is required</small>
</div>
And validation worked like a charm

Using Automapper to map viewmodel to domain model returns nulls in POST action?

I have a entity model that records some employee information. I have a similar view model.
In my create action I create a new instance of the viewmodel and pass a few lists for dropdowns.
In my Create Post action I map using AutoMapper the returned view model to the entity model.
I am doing something wrong because the posted back data doesn't seem to contain any of the view model data. It just contains nulls.
Any ideas what I am doing wrong?
Controller
// GET: /TimeCreditEntries/Create
public ActionResult Create()
{
var Model = new TimeCreditEntryViewModel(); //Create a new viewmodel to hold the TimeCreditEntry
Model.StationList = new SelectList(getStations(), "StationId", "Code");
Model.AuthorisedEmployee = new SelectList(getEmployees(), "EmployeeId", "FullNameSurnameFirst");
Model.AuthorisedPayment = new SelectList(getPaymentTypes(), "PaymentTypeId", "Code");
return View(Model); //View is returned with model as parameter.
}
// POST: /TimeCreditEntries/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "TimeCreditEntryId,RecordedDate,TimeCreditDate,ShiftId,StationId,AuthorisingEmployeeId,AuthorisedEmployeeId,ModifiedDate")] TimeCreditEntryViewModel timeCreditEntry)
{
if (ModelState.IsValid)
{
Mapper.CreateMap<TimeCreditEntryViewModel, TimeCreditEntry>();
db.TimeCreditEntries.Add(Mapper.Map<TimeCreditEntryViewModel, TimeCreditEntry> (timeCreditEntry));
db.SaveChanges();
return RedirectToAction("Register"); }
ViewBag.AuthorisedEmployeeId = new SelectList(db.Employees, "EmployeeId", "Title", timeCreditEntry.AuthorisedEmployeeId);
ViewBag.AuthorisingEmployeeId = new SelectList(db.Employees, "EmployeeId", "Title", timeCreditEntry.AuthorisingEmployeeId);
ViewBag.ShiftId = new SelectList(db.Shifts, "ShiftId", "Code", timeCreditEntry.ShiftId);
return View(timeCreditEntry);
}
View
#model ATAS.Models.ViewModels.TimeCreditEntryViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<fieldset>
<legend>Request to use time credit</legend>
<div class="form-group">
<label class="col-md-2 control-label" for="AuthorisedEmployee">Who</label>
<div class="col-md-2">
#Html.DropDownListFor(model => model.AuthorisedEmployee, Model.AuthorisedEmployee, "Select Employee", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.AuthorisedEmployeeId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TimeCreditDate, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.TimeCreditDate, new { #class = "datepicker", id = "vacation" })
#Html.ValidationMessageFor(model => model.TimeCreditDate)
</div>r
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="StationList">Where</label>
<div class="col-md-2">
#Html.DropDownListFor(model => model.StationList, Model.StationList, "Choose Station", new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="Shift">Which</label>
<div class="col-md-2">
#Html.DropDownList("Shift", new SelectList(string.Empty, "Value", "Text"), new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button class="btn btn-default" type="reset">Cancel</button>
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
</fieldset>
</div>
}
<script src="~/Scripts/jquery-2.1.4.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('.datepicker').datepicker()
$("#Shift").prop("disabled", true);
//Dropdownlist Selectedchange event
$("#StationList").change(function () {
$("#Shift").empty();
if ($("#StationList").val() != "") {
$.ajax({
type: 'POST',
url: '#Url.Action("GetShiftsByStation")', // we are calling json method
dataType: 'json',
data: { selectedValue: $("#StationList").val() },
// here we are get value of selected Station and passing same value as input to json method GetShifts.
success: function (shiftList) {
// states contains the JSON formatted list
// of states passed from the controller
$("#Shift").append('<option value="' + null + '">' + "Choose shift" + '</option>');
$.each(shiftList, function (i, shift) {
$("#Shift").append('<option value="' + shift.Value + '">' + shift.Text + '</option>');
// here we are adding option for shifts
$("#Shift").prop("disabled", false);
});
},
error: function (ex) {
alert('Failed to retrieve shifts.' + ex);
}
});
return false;
}
else {
$("#Shift").empty();
$("#Shift").prop("disabled", true);
}
})
});

Place Partial View Html elements below the Main View's Html elements

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());

Resources