ASP.NET MVC4 IEnumerable empty on post - c#

I have read several answers on this issue but despite this, it would appear I have developed code blindness.
I have the following view model:
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual IEnumerable<ProductSimpleResponse> ProductSimpleResponse { get; set; }
}
This is then passed into a view and then a partial view:
#model Websites.ViewModels.IndividualProductVm #{ ViewBag.Title = "Edit"; }
<h2>Edit</h2>
#using (Html.BeginForm(null, null, FormMethod.Post, new { name = "form", id = "mainForm" })) { #Html.AntiForgeryToken() #Html.ValidationSummary(true, "", new { #class = "text-danger" }) #Html.HiddenFor(model => model.Products.Id) #Html.HiddenFor(model
=> model.ProductSummary.SupplierId) Html.RenderPartial("_IndividualProduct", Model);
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index", new { id = Model.ProductSummary.SupplierId }, new { #class = "btn btn-default" })
</div>
#section Scripts { #Scripts.Render("~/bundles/jqueryval") }
#model Websites.ViewModels.IndividualProductVm
<div>
#Html.LabelFor(model => model.Products.ProductCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductCode, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div style="clear:both;"></div>
<div>
#Html.LabelFor(model => model.Products.ProductDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductDescription, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<table class="table">
<tr>
<th>
Present
</th>
</tr>
#foreach (var item in Model.ProductSimpleResponse)
{
<tr>
#Html.HiddenFor(modelItem => item.Id)
#Html.HiddenFor(modelItem => item.SupplierId)
#Html.HiddenFor(modelItem => item.ProductCode)
<td>
#Html.EditorFor(modelItem => item.Present)
</td>
</tr>
}
</table>
However, when I enter the edit post, my viewmodel is null for the IEnumerable<ProductSimpleResponse> but fine for the other two classes.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(IndividualProductVm model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index", new { id = model.ProductSummary.SupplierId });
}
return View(model.Products);
}
If someone can explain what I'm doing wrong, I'd be most grateful.

Your property name is ProductSimpleResponse, alhtough the type is ProductSvhcSimpleResponse, so to iterate through it you should have.
#foreach (var item in Model.ProductSimpleResponse)
NOT
#foreach (var item in Model.ProductSvhcSimpleResponse)

use List because
IEnumerable is suitable just for iterate through collection and you can not modify (Add or Remove) data IEnumerable bring ALL data from server to client then filter them, assume that you have a lot of records so IEnumerable puts overhead on your memory.
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual List<ProductSvhcSimpleResponse> ProductSimpleResponse { get; set; }
}
More help click here

Related

Pass id of parent view to child view and use it in controller - ASP.NET MVC 5

I am having a problem sending parent ID to child ID, even if I do, I want to display the child's data only of a particular parent. In my code, List is the parent, and Notes are the children. When I create a List, I have redirected to Notes Index Page (Different Controller) along with ID but in all lists, I can see the same notes. I am using TempData in NotesController to keep hold of that ID.
List Controller:
//Index
public ActionResult Index()
{
return View(db.Lists.ToList());
}
//Create
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ListViewModel lists)
{
if (ModelState.IsValid)
{
Lists list = new Lists();
list.CreationDate = DateTime.Now;
list.ListName = lists.ListName;
db.Lists.Add(list);
db.SaveChanges();
int? idFromView = list.Id;
return RedirectToAction("Index", "NotesInLists", new { id = idFromView });
}
return View(lists);
}
Notes Controller:
//Index
public ActionResult Index(int? id)
{
TempData["idFromView"] = id;
return View(db.NotesInLists.ToList());
}
//Create
public ActionResult CreateWithtext()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateWithtext(NoteTagViewModel notesInList)
{
if (ModelState.IsValid)
{
List<string> TagsList = notesInList.TagsList.Split(',').ToList();
NotesInList note = new NotesInList();
int tempDataId = (int)TempData["idFromView"];
note.CreationDate = DateTime.Now;
note.ListName = notesInList.ListName;
note.TextDescription = notesInList.TextDescription;
note.listID = tempDataId;
db.NotesInLists.Add(note);
db.SaveChanges();
//saving tags
foreach (var item in TagsList)
{
Tags tag = new Tags();
tag.CreationDate = DateTime.Now;
tag.TagName = item;
tag.Note_Id = note.Id;
db.Tags.Add(tag);
}
db.SaveChanges();
return RedirectToAction("Index", new { id = tempDataId });
}
return View(notesInList);
}
Here, in this NotesController, I am also saving tags and it is working fine, but the main issue is with List. Also using ViewModels but that is of no concern to me for now. If I try accessing List using
Lists list = new List();
I still am not able to check and compare that ID with that List ID, it throws an exception.
List Model:
namespace NoteBlocks.Models
{
public class Lists
{
public int Id { get; set; }
[Required]
[Display(Name = "List Name")]
public string ListName { get; set; }
[Display(Name = "Creation Date")]
public DateTime? CreationDate { get; set; }
[Display(Name = "Last Updated")]
public DateTime? UpdateDate { get; set; }
}
}
List ViewModel:
namespace NoteBlocks.ViewModels
{
public class ListViewModel
{
public int Id { get; set; }
[Required]
[Display(Name = "List Name")]
public string ListName { get; set; }
[Display(Name = "Creation Date")]
public DateTime? CreationDate { get; set; }
[Display(Name = "Last Updated")]
public DateTime? UpdateDate { get; set; }
}
}
Notes Model:
namespace NoteBlocks.Models
{
public class NotesInList
{
public int Id { get; set; }
[Required]
[Display(Name = "List Name")]
public string ListName { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Creation Date")]
public DateTime? CreationDate { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Last Updated")]
public DateTime? UpdateDate { get; set; }
public string customFile { get; set; }
[Display(Name = "Enter Note Content")]
public string TextDescription { get; set; }
public Lists List { get; set; }
public int listID { get; set; }
}
}
Notes ViewModel:
namespace NoteBlocks.Models
{
public class NoteTagViewModel
{
public int NoteId { get; set; }
[Required]
[Display(Name = "List Name")]
public string ListName { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Creation Date")]
public DateTime? CreationDate { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Last Updated")]
public DateTime? UpdateDate { get; set; }
public string customFile { get; set; }
[Display(Name = "Enter Note Content")]
public string TextDescription { get; set; }
//multiple tags
public string TagsList { get; set; }
public Lists List { get; set; }
public int ListId { get; set; }
}
}
Created a foreign key but it is not working.
HTML - List Index
#model IEnumerable<NoteBlocks.Models.Lists>
#{
ViewBag.Title = "List";
//ViewBag.Id = model.Lists.Id;
}
<h2>List</h2>
<p>
#Html.ActionLink(" Create New List", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ListName)
</th>
<th>
#Html.DisplayNameFor(model => model.CreationDate)
</th>
<th>
#Html.DisplayNameFor(model => model.UpdateDate)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
//using ActionLink to open list of notes for that particular List
//and passing particular List ID from here if already created
#Html.ActionLink(item.ListName, "Index", "NotesInLists", new { id = item.Id }, null)
#*#TempData.Peek("tempDataId")*#
</td>
<td>
#Html.DisplayFor(modelItem => item.CreationDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.UpdateDate)
</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 - List Create
#model NoteBlocks.Models.Lists
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>List</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ListName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ListName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ListName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreationDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CreationDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CreationDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UpdateDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UpdateDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UpdateDate, "", new { #class = "text-danger" })
</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>
#Html.ActionLink("Back to List", "Index")
</div>
HTML - Notes Index
#model IEnumerable<NoteBlocks.Models.NotesInList>
#{
ViewBag.Title = "List Notes";
}
<h2>List Notes</h2>
<p id="buttonsInPTag">
<button type="button" class="btn btn-primary" id="addButton1"><span class="glyphicon glyphicon-plus">#Html.ActionLink(" Create Textual Note", "CreateWithtext")</span></button>
<button type="button" class="btn btn-primary" id="addButton2"><span class="glyphicon glyphicon-plus">#Html.ActionLink(" Create Note from Document", "CreateWithDoc")</span></button>
<button type="button" class="btn btn-primary" id="addButton3"><span class="glyphicon glyphicon-plus">#Html.ActionLink(" Create Image Note", "CreateWithImage")</span></button>
<button type="button" class="btn btn-primary" id="addButton4"><span class="glyphicon glyphicon-plus">#Html.ActionLink(" Create Audio / Video Note", "CreateWithMedia")</span></button>
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ListName)
</th>
<th>
#Html.DisplayNameFor(model => model.CreationDate)
</th>
<th>
#Html.DisplayNameFor(model => model.UpdateDate)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ListName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreationDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.UpdateDate)
</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 - Notes CreateWithText
#model NoteBlocks.Models.NoteTagViewModel
#{
ViewBag.Title = "Create Note with Text";
}
<h2>Create Note with Text</h2>
#using (Html.BeginForm("CreateWithText", "NotesInLists", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ListName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ListName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ListName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TextDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<textarea cols="50" rows="12" class=form-control id="TextDescription" name="TextDescription"></textarea>
#Html.ValidationMessageFor(model => model.TextDescription, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label("Tags", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="text" id="tagsField" name="tagsField" class=form-control data-role="tagsinput" />
<input type="hidden" name="TagsList" id="TagsList" />
</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>
#Html.ActionLink("Back to List", "Index")
</div>
#section scripts
{
<script>
$(document.body).on('focusout', '.bootstrap-tagsinput input', () => {
let array = $('#tagsField').tagsinput('items');
$("#TagsList").val(array);
})
</script>
}
I am stuck to this point. Please guide. p.s. using code first approach.
There is no filter applied to the query that gets notes in your Index action of notes controller.
I think adding where method;
.Where(x=>x.listID == id)
will solve your problem.
//Index
public ActionResult Index(int? id)
{
TempData["idFromView"] = id;
return View(db.NotesInLists/*.Where(x=>x.listID == id)*/.ToList());
}

How to bind value from UI to controller with complex model in c# mvc

I'm new to .net. I have this model that has been a real trouble for me for days.
class DetailedRecordModel
public class DetailedRecordModel
{
public string RecordID { get; set; }
public string EmployeeID { get; set; }
public string CustomerID { get; set; }
[DataType(DataType.Date)]
public string InitDate { get; set; }
[DataType(DataType.Date)]
public string DeliveryDate { get; set; }
public virtual ICollection<PurchaseDetail> detail{ get; set; }
}
class PurchaseDetail
public class PurchaseDetail
{
public string ProductID { get; set; }
public int Qty { get; set; }
public double price { get; set; }
public string RecordID { get; set; }
}
controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DetailedRecordModel record)
{
if (ModelState.IsValid)
{
return View(record);
}
return RedirectToAction("ViewRecords");
}
html
<div class="form-group">
#Html.LabelFor(model => model.EmployeeID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.EmployeeID, (IEnumerable<SelectListItem>)ViewData["sellistemp"])
#Html.ValidationMessageFor(model => model.EmployeeID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CustomerID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.CustomerID, (IEnumerable<SelectListItem>)ViewData["sellistcust"])
#Html.ValidationMessageFor(model => model.CustomerID, "", new { #class = "text-danger" })
</div>
</div>
<tr>
<td style="display:none" id="Index0" name="detail.Index" value="0"></td>
<td>1</td>
<td id="ProductID" name="detail[0].ProductID" value="sp00002">sp00002</td>
<td id="Qty" name="detail[0].Qty" value="12123">12123</td>
<td id="price" name="detail[0].price" value="2312">2312</td>
</tr>
<tr>
<td style="display:none" id="Index1" name="detail.Index" value="1"></td>
<td>2</td>
<td id="ProductID" name="detail[1].ProductID" value="sp00003">sp00003</td>
<td id="Qty" name="detail[1].Qty" value="2323">2323</td>
<td id="price" name="detail[1].price" value="3223">3223</td>
</tr>
for RecordID, EmployeeID, CustomerID, InitDate and DeliveryDate passing them to the controller is all fine, however I always get null for <PurchaseDetail> detail. How can I solve this problem?
you have to pass the model to the view by using View(myModel) or RedirectToAction("ViewRecords", record)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DetailedRecordModel record)
{
if (ModelState.IsValid)
{
return RedirectToAction("ViewRecords", record);
}
return View(record);
}
public IActionResult ViewRecords(DetailedRecordModel model)
{
return View(model);
}
then in the View you can access the model like here How to pass model in MVC view
add the definition of your model at the top of #model DetailedRecordModel;
after you added the model you can access it everywhere in your file with #Model (in html) or Model
#model DetailedRecordModel;
#{
ViewData["Title"] = "ViewRecords";
}
<h1>ViewRecords</h1>
<div class="form-group">
#Html.LabelFor(model => model.EmployeeID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.EmployeeID, (IEnumerable<SelectListItem>)ViewData["sellistemp"])
#Html.ValidationMessageFor(model => model.EmployeeID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CustomerID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.CustomerID, (IEnumerable<SelectListItem>)ViewData["sellistcust"])
#Html.ValidationMessageFor(model => model.CustomerID, "", new { #class = "text-danger" })
</div>
</div>
#foreach (var entry in Model.detail)
{
<tr>
<td style="display:none" id="Index0" name="detail.Index" value="0"></td>
<td>1</td>
<td id="ProductID" name="#entry.ProductID" value="sp00002">sp00002</td>
<td id="Qty" name="#entry.Qty" value="12123">12123</td>
<td id="price" name="#entry.price" value="2312">2312</td>
</tr>
}
After 2 wretching days of desperation I know that in order to bind the values, I found the answer by declaring an object DetailedRecordModel inside model PurchaseDetail and I have to change the name of each <input> tag into detail[index].somevariable

How can I view both table and form in same view

I have recently learning ASP.NET MVC5.
I am trying to see both the form and a table(return as partialview) in one view but i'm getting this error.
System.NullReferenceException: Object reference does not set to an instance of an object.
Here is my Model:
public class Prescription
{
[Key]
public int PrescriptionID { get; set; }
[ForeignKey("Assessment")]
public int? AssessmentID { get; set; }
public Assessment Assessment { get; set; }
[ForeignKey("Medicine")]
[Display(Name ="Prescription")]
public int? MedcineID { get; set; }
public Medicine Medicine { get; set; }
}
My main view where I want to put my partial view:
#using ClinicManagemet
#model ClinicManagemet.Models.Prescription
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Prescription</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.MedcineID, "MedcineID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("MedcineID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MedcineID, "", new { #class = "text-danger" })
</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>
}
#Html.Action("ViewPrescription","Assessments")
<div>
#Html.ActionLink("Back to Home", "Home")
</div>
My partial view:
#model IEnumerable<ClinicManagemet.Models.Prescription>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Assessment.Complaint)
</th>
<th>
#Html.DisplayNameFor(model => model.Medicine.MedicineName)
</th>
<th></th>
</tr>
#foreach (var item in Model) { //Here is the line where I get the error
<tr>
<td>
#Html.DisplayFor(modelItem => item.Assessment.Complaint)
</td>
<td>
#Html.DisplayFor(modelItem => item.Medicine.MedicineName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.PrescriptionID }) |
#Html.ActionLink("Details", "Details", new { id=item.PrescriptionID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.PrescriptionID })
</td>
</tr>
}
</table>
My partial view's controller:
public ActionResult ViewPrescription()
{
return PartialView();
}
Edit: If I fix this, I'll try to add Ajax so whenever I insert something, it will just refresh the partial view.
Load your partial view like this,
#{
Html.RenderAction("ViewPrescription","YourControllerName")
}
And in your ViewPrescription method, return the data,
{
//Fetch the data here
return PartialView(model);
}
Hope it helps.
You're not passing a model into the partial view when returning the view.
public ActionResult ViewPrescription()
{
ClinicManagemet.Models.Prescription model = _service.GetPerscription();
return PartialView(model);
}

MVC Passing a Complex Object to the controller for saving

I am writing a web page with MVC and Entity Framework.
I have an order with line items attached and want to return a complex object to the controller for processing.
I have now included all the code.
My view:
#model BCMManci.ViewModels.OrderCreateGroup
#{
ViewBag.Title = "Create";
}
<h2>New Order</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h4>#Html.DisplayFor(model => model.Order.Customer.FullName)</h4>
<table>
<tr>
<td><b>Order Date:</b> #Html.DisplayFor(model => model.Order.OrderDate)</td>
<td><b>Status:</b> #Html.DisplayFor(model => model.Order.OrderStatus.OrderStatusName)</td>
</tr>
<tr>
<td colspan="2">
<b>Notes</b>
#Html.EditorFor(model => model.Order.Notes, new { htmlAttributes = new { #class = "form-control" } })
</td>
</tr>
</table>
#Html.ValidationMessageFor(model => model.Order.Notes, "", new { #class = "text-danger" })
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table class="table table-striped table-hover">
<thead>
<tr>
<td>Name</td>
<td>Price</td>
<td>Discount</td>
<td>Total</td>
<td>Quantity</td>
</tr>
</thead>
<tbody>
#foreach (var product in Model.ProductWithPrices)
{
<tr>
<td>
#Html.DisplayFor(modelItem => product.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => product.SellingPrice)
</td>
<td>
#Html.DisplayFor(modelItem => product.DiscountPrice)
</td>
<td>
#Html.DisplayFor(modelItem => product.TotalPrice)
</td>
<td>
#Html.EditorFor(modelItem => product.Quantity, new { htmlAttributes = new { #class = "form-control" } })
</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="Create" class="btn btn-default" />
}
<div class="btn btn-danger">
#Html.ActionLink("Cancel", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Order,ProductWithPrices,Order.Note,product.Quantity")] OrderCreateGroup order)
{
try
{
if (ModelState.IsValid)
{
db.Orders.Add(order.Order);
foreach (var orderItem in order.ProductWithPrices.Select(item => new OrderItem
{
OrderId = order.Order.OrderId,
ProductId = item.ProductId,
Quantity = item.Quantity,
ItemPrice = item.SellingPrice,
ItemDiscount = item.DiscountPrice,
ItemTotal = item.TotalPrice
}))
{
db.OrderItems.Add(orderItem);
}
db.SaveChanges();
return RedirectToAction("ConfirmOrder", new {id = order.Order.OrderId});
}
}
catch (DataException /* dex */)
{
//TODO: Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
ViewBag.Products = db.Products.Where(model => model.IsActive == true);
PopulateDropdownLists();
return View(order);
}
Data Source:
public class OrderCreateGroup
{
public OrderCreateGroup()
{
ProductWithPrices = new List<ProductWithPrice>();
}
public Order Order { get; set; }
public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}
public class ProductWithPrice : Product
{
public decimal SellingPrice { get; set; }
public decimal DiscountPrice { get; set; }
public int Quantity { get; set; }
public decimal TotalPrice { get; set; }
}
However, the values that are entered on the form are not being passed, through. So I can't access them in the controller. The 'productWithPrices' collection is null although there is Data in it on the web page.
I have tried making it asyc and also tried changing the ActionLink button like below but it didn't get to the controller.
#Html.ActionLink("Create", "Create", "Orders", new { orderCreateGoup = Model }, null)
This is the controller but it now doesn't make sense as the parameter passed in the datasource for the page.
public ActionResult Create(OrderCreateGroup orderCreateGoup)
Please, can you give me direction on the best way of doing this?
In your OrderCreateGroup class initialize the collection to an empty list.
public class OrderCreateGroup
{
public OrderCreateGroup()
{
ProductWithPrices = new List<ProductWithPrice>();
}
public Order Order { get; set; }
public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}
You'll need to add #Html.HiddenFor(m => m.SellingPrice) and similarly for other bound fields that are using DisplayFor if you want to post them back to the controller.
Note: For your benefit, try to have a look at the generated HTML code when your page is rendered in the browser and see what tags are generated inside the <form> tag with a name attribute.
make sure you bind the appropriate property from the complex object, like the following:
#model BCMManci.ViewModels.OrderCreateGroup
...
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OrderCreateGroup.Order.Quantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OrderCreateGroup.Order.Quantity, "", new { #class = "text-danger" })
</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>
#Html.ActionLink("Back to List", "Index")
</div>
Note:model.OrderCreateGroup.Order.Quantity would be one the your order's property.
hope this helps.

TextboxFor passes text, but RadioButtonFor does not

I'm trying to pass a RadioButtonFor to the model.
Controller
[HttpPost]
public ActionResult Contact(ApplicationCommentType model)
{
//send email here
//reload form
ApplicationCommentType appdata = new ApplicationCommentType();
appdata.CommentTypeData = db.CommentTypes.ToList();
return View(appdata);
}
ApplicationCommentType
public class ApplicationCommentType
{
public IEnumerable<CommentType> CommentTypeData { get; set; }
public String CommentTypeDataSelection { get; set; }
public String Name { get; set; }
public String Email { get; set; }
public String Comment { get; set; }
}
CommentType
public partial class CommentType
{
public int CommentTypeID { get; set; }
public string CommentTypeDesc { get; set; }
}
View
#using(#Html.BeginForm("Contact", "Home", FormMethod.Post, new{ #class ="form-horizontal"})){
<fieldset>
<legend>Contact Us</legend>
<div class="form-group">
#Html.LabelFor(x => x.Email, new {#class="col-lg-2 control-label"})
<div class="col-lg-10">
#Html.TextBoxFor(x => x.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(x => x.Name, new { #class = "col-lg-2 control-label" })
<div class="col-lg-10">
#Html.TextBoxFor(x => x.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<label for="textArea" class="col-lg-2 control-label">Questions, Comments, or Concerns</label>
<div class="col-lg-10">
#Html.TextAreaFor(x => x.Comment, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">Comment Type</label>
<div class="col-lg-10">
#foreach (var item in Model.CommentTypeData)
{
<div class="radio">
<label>
#Html.RadioButtonFor(x => x.CommentTypeData, item.CommentTypeDesc)
#Html.LabelFor(m => m.CommentTypeData, item.CommentTypeDesc, item.CommentTypeID)
</label>
</div>
}
#Html.HiddenFor(x => x.CommentTypeDataSelection)
</div>
</div>
</fieldset>
}
Now this kind of works, all the textbox items work. Placing a break point on the [HttpPost] return yields the following values.
Comment: "awesome"
CommentTypeData: Count = 0
CommentTypeDataSelection: null
Email: "example#example.com"
Name: "John Smith"
Shouldn't CommentTypeData have a count? If I check the request the selected value is there.
Request.Params["CommentTypeData"]: "General Improvement Suggestion"
So why is the Model not updated? Is it a requirement to manually update the Model from the Request object?
You can use #Html.RadioButtonFor but you should make sure that item.CommentTypeDesc compatible with Radio type.
Refer to MVC4: Two radio buttons for a single boolean model property
Hope it helps.

Categories

Resources