foreach(var item => model.xxxx) Null Exceptions [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
I have gone through lot of posts however unable to resolve this issue.
I input some values on the View and click the Submit button
My repo calculates the payment schedule based on the criteria and displays the list (that's what I am trying to achieve)
This is where I am having issues.
On the initial load my Model is null and I get the null reference exception.
I have just started coding with asp so please ignore the basics in this case.
Any suggestions would be helpful
#model FinanceApplication.ViewModels.LoanViewModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div>
<table style="width: 35%;" class="style1">
<tr>
<td>Enter Price</td>
<td>#Html.TextBoxFor(model => model.Amount)</td>
</tr>
<tr>
<td>Enter Deposit</td>
<td>#Html.TextBoxFor(model => model.Deposit)</td>
</tr>
<tr>
<td>Finance Option</td>
<td>
#Html.DropDownListFor(model =>
model.Term, new SelectList(Enum.GetValues(typeof(Options))),
"Select Option",
new { #class = "form-control" })
</td>
</tr>
<tr>
<td>Delivery Date</td>
<td>
#Html.EditorFor(model => model.Deliverydate)
</td>
</tr>
<tr>
<td>Arrangement Fee</td>
<td>#Html.TextBoxFor(model => model.ArrangementFee)</td>
</tr>
<tr>
<td>Completion Fee</td>
<td>#Html.TextBoxFor(model => model.CompletionFee)</td>
</tr>
<tr>
<td>
<input type="submit" id="btnSubmit"
value="Submit" onclick="myFunction();" />
</td>
</tr>
</table>
</div>
<div id="loan-form" class="text-left">
<h1>Payment Schedule</h1>
<table>
<tr>
<td>Amount (£) </td>
<td>#Html.DisplayFor(model => model.Amount)</td>
</tr>
<tr>
<td>Loan Amount (£) </td>
<td>#Html.DisplayFor(model => model.LoanAmount)</td>
</tr>
<tr>
<td>Deposit (£) </td>
<td>#Html.DisplayFor(model => model.Deposit)</td>
</tr>
<tr>
<td>Term (years) </td>
<td>#Html.DisplayFor(model => model.Term)</td>
</tr>
<tr>
<td>Delivery Date</td>
<td>#Html.DisplayFor(model => model.Deliverydate)</td>
</tr>
<tr>
<td>
<table class="table table-striped">
<thead>
<tr>
<th>Payment Date</th>
<th>Payment Amount (£) </th>
<th>Total Paid (£) </th>
<th>Balance (£) </th>
</tr>
</thead>
<tbody>
if(Model != null)
{
#foreach (var item in Model.PaymentSchedule)
{
<tr>
<td> #Html.DisplayFor(modelItem =>
item.PaymentDate) </td>
<td> #Html.DisplayFor(modelItem =>
item.PaymentAmount) </td>
<td> #Html.DisplayFor(modelItem =>
item.TotalPaid) </td>
<td> #Html.DisplayFor(modelItem =>
item.RemainingBalance) </td>
</tr>
}
}
else
{
<tr>
<td>No Items found</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
</table>
</div>
}
{
private IPaymentScheduleRepository _paymentScheduleRepository;
public HomeController(IPaymentScheduleRepository paymentScheduleRepository)
{
_paymentScheduleRepository = paymentScheduleRepository; }
[HttpGet]
public IActionResult Index()
{ return View(new LoanViewModel()); }
[HttpPost]
public async Task<IActionResult> Index(LoanViewModel requestParameters)
{ LoanViewModel output = await _paymentScheduleRepository.GetPaymentSchedule(requestParameters);
return View("Index", output);}}
//ViewModel
public class LoanViewModel
{
[Required(ErrorMessage = "Please enter the loan amount.")]
[Range(1, 100000000,
ErrorMessage = "Loan amount must be between 1,000 and 1000,000.")]
public decimal Amount { get; set; }
[Required(ErrorMessage = "Please enter the deposit amount.")]
[Remote(action: "VerifyDeposit", controller:"Home")]
public decimal Deposit { get; set; }
[Required(ErrorMessage = "Please select the term of the loan.")]
public string Term { get; set; }
[Required(ErrorMessage = "Please select the delivery date.")]
[DataType(DataType.Date)]
[Display(Name = "Delivery Date")]
[DisplayFormat(ApplyFormatInEditMode = true,
DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime Deliverydate { get; set; }
public decimal ArrangementFee { get; set; }
public decimal CompletionFee { get; set; }
public decimal LoanAmount
{
get { return (Amount - Deposit); }
}
[Display(Name = "Payment Schedule")]
public List<SheduledPayments> PaymentSchedule { get; set; }
}
//PaymentSchedule
public class SheduledPayments
{
public DateTime PaymentDate { get; set; }
public decimal PaymentAmount { get; set; }
public decimal RemainingBalance { get; set; }
public decimal TotalPaid { get; set; }
}

On the initial load your view model returns null - hint.
You should have a method for loading the view i.e get and a method for posting the view i.e. post.
Depending on context you need to work with the model in both action methods.
Check this and post the action method on your initial load.

For the decimal values you can use the ?? operator, for the date you can use the ternary operator ?:
. . .
<td>#Html.DisplayFor((modelItem => (item.PaymentDate == null ? new DateTime(1900,1,1):item.PaymentDate)))</td>
<td>#Html.DisplayFor(modelItem => item.PaymentAmount ?? 0)</td>
. . .
see this for more informations.
Otherway If the problem is the first call, your model is not defined so you must initialize the parameters in the model constructor.

Related

how do I get user input from the view and use it in my controller

I am trying to get the user's input PurchaseAmount from view and use that input for my logic, if the PurchaseAmount > CardFunds, then it'll print a message "Insufficient Funds", if the Purchase < CardFunds, it'll process to the next statement.
I declared the PurchaseAmount and CardFunds in my .cs file as such:
namespace Form6.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class User
{
public int UserID { get; set; }
public int PurchaseAmount { get; set; }
public int CardFunds { get; set; }
}
}
PurchaseAmount will be given by the user, CardFunds is an Int datatype value previously storeed in the database.
and below is what I have for the controller :
namespace Form6.Controllers
{
public class LoginController : Controller
{
// GET: Login
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Authorize(Form6.Models.User userModel)
{
using (Form6Entities db = new Form6Entities())
{
var userDetails = db.Users.Where(x => x.Username == userModel.Username && x.Password == userModel.Password).FirstOrDefault();
var cardDetails = db.Users.Where(x=> x.FirstName == userModel.FirstName && x.LastName == userModel.LastName && x.CardNum == userModel.CardNum && x.ExpDate == userModel.ExpDate && x.CVV == userModel.CVV).FirstOrDefault();
var fundStatus = db.Users.Where(x => x.CardFunds == userModel.CardFunds).FirstOrDefault();
var purchaseAmount =
if (userDetails == null)
{
userModel.LoginErrorMessage = "Unauthorized for this transaction!";
return View("Index", userModel);
}
else if (PurchaseAmount > userModel.CardFunds)
{
userModel.LoginErrorMessage = "Insufficient Funds";
return View("Index", userModel);
}
else
{
Session["userID"] = userDetails.UserID;
return RedirectToAction("Index", "Home");
}
}
}
all the other logics are working properly such as verifying username and password, and all the cardDetaills inputs
how should I declare the variable PurchaseAmount in the controller with the user's input from the view file
and this will be the view's code:
<div id="login-div">
#using(Html.BeginForm("Authorize", "Login",FormMethod.Post))
{
<table>
<tr>
<td></td>
<td style="text-decoration:underline">Payment Gateway</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Username)</td>
<td>#Html.EditorFor(model => model.Username)
<td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.Username)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Password) </td>
<td>#Html.EditorFor(model => model.Password)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.Password)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.FirstName) </td>
<td>#Html.EditorFor(model => model.FirstName)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.LastName) </td>
<td>#Html.EditorFor(model => model.LastName)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.LastName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.CardNum) </td>
<td>#Html.EditorFor(model => model.CardNum)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.CardNum)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.ExpDate) </td>
<td>#Html.EditorFor(model => model.ExpDate)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.ExpDate)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.CVV) </td>
<td>#Html.EditorFor(model => model.CVV)</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.CVV)</td>
</tr>
<tr>
<td colspan="2">
<label class="field-validation-error">#Html.DisplayFor(model =>model.LoginErrorMessage) </label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="name" value="Submit" />
</td>
</tr>
</table>
}
How should I declare the variable PurchaseAmount in the controller with the user's input from the view file?
In this scenario you should have two models. One is your User Base Model and another for Purchase info Model. You can think of below model.
UserPurchaseinfo Model:
public class UserPurchaseinfo
{
public int UserID { get; set; }
public int PurchaseAmount { get; set; }
public int CardFunds { get; set; }
}
Note: As you already have User Model should I have renamed as UserPurchaseinfo to reduce ambiguity.
Modify Existing User Model:
public class UserModel
{
public string FullName { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CardNum { get; set; }
public DateTime ExpDate { get; set; }
public string CVV { get; set; }
public UserPurchaseinfo UserPurchaseinfo { get; set; }
}
Note: As you noticed that we have added UserPurchaseinfo in UserModel class so that we can take input from same view.
View:
#model DotNet6MVCWebApp.Models.UserModel
<div id="login-div">
#using (Html.BeginForm("PostPaymetInfo", "YourControllerName", FormMethod.Post))
{
<table>
<tr>
<td></td>
<td><strong style="text-decoration:underline;margin-left:25px;">Payment Gateway</strong></td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Username)</td>
<td>#Html.EditorFor(model => model.Username,new { htmlAttributes = new { #class = "form-control"}})
<td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.Username)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Password) </td>
<td>#Html.EditorFor(model => model.Password,new { htmlAttributes = new { #class = "form-control",type = "password"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.Password)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.FirstName) </td>
<td>#Html.EditorFor(model => model.FirstName,new { htmlAttributes = new { #class = "form-control"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.LastName) </td>
<td>#Html.EditorFor(model => model.LastName,new { htmlAttributes = new { #class = "form-control"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.LastName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.CardNum) </td>
<td>#Html.EditorFor(model => model.CardNum,new { htmlAttributes = new { #class = "form-control"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.CardNum)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.ExpDate) </td>
<td>#Html.EditorFor(model => model.ExpDate,new { htmlAttributes = new { #class = "form-control"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.ExpDate)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.CVV) </td>
<td>#Html.EditorFor(model => model.CVV,new { htmlAttributes = new { #class = "form-control"}})</td>
</tr>
<tr>
<td></td>
<td>#Html.ValidationMessageFor(model => model.CVV)</td>
</tr>
<tr>
<td></td>
<td><strong style="text-decoration:underline;margin-left:25px;">User Purchase Info</strong></td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.UserPurchaseinfo.PurchaseAmount) </td>
<td>#Html.EditorFor(model => model.UserPurchaseinfo.PurchaseAmount,new { htmlAttributes = new { #class = "form-control",type = "number"}})</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.UserPurchaseinfo.CardFunds) </td>
<td>#Html.EditorFor(model => model.UserPurchaseinfo.CardFunds,new { htmlAttributes = new { #class = "form-control",type = "number"}})</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="name" class="btn btn-success" value="Submit" />
</td>
</tr>
</table>
}
</div>
View Output:
Controller:
[HttpPost]
public ActionResult PostPaymetInfo(UserModel paymentModel)
{
// You can check and validate all the property which you are sending from your view
// Now Check your PurchaseAmount here whatever you are getting on paymentModel
return RedirectToAction("Index");
}
Final Output:
Basically you need to add your UserPurchaseinfo into your User Model so that you can access both property on your view finally you can take input from there and can submit above way.

Access variable of one controller from another view in ASP.NET Core MVC

I am trying build a project while self learning but have been stuck in one place.
I have this class Roles:
namespace IC2021.Models
{
public partial class Roles
{
public Roles()
{
Staffs = new HashSet<Staffs>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Staffs> Staffs { get; set; }
}
}
And another called Staffs:
namespace IC2021.Models
{
public partial class Staffs
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Location { get; set; }
public int? RoleId { get; set; }
public string Archived { get; set; }
public virtual Roles Role { get; set; }
}
}
This is my RolesController:
namespace IC2021.Controllers
{
public class RolesController : Controller
{
private readonly ICOctober2021Context _context;
public RolesController(ICOctober2021Context context)
{
_context = context;
}
// GET: Roles
public async Task<IActionResult> Index()
{
return View(await _context.Roles.ToListAsync());
}
public async Task<IActionResult> RolesWithStaffs()
{
var iCOctober2021Context = _context.Roles.Include(s => s.Staffs);
return View(await iCOctober2021Context.ToListAsync());
}
}
}
And finally I'm trying to view it from RolesWithStaffs:
<!-- model declaration -->
#model IEnumerable<IC2021.Models.Roles>
#{
ViewData["Title"] = "RolesWithViewController";
}
<h1>RolesWithViewController</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Role
</th>
<th>
Staff Name
</th>
<th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Staffs)
</td>
#*<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>*#
</tr>
}
</tbody>
</table>
So here in the view when I tried to access from Staffs, I am not able (for example item.Staffs.FirstName, or anything else from Staffs). Whereas I can do it other way, I mean from staffs view I can access Roles.Name or Id).
Can anyone please help me? Any help will be highly appreciated.
Your view model looks quite unusual, IMHO you can try this
public async Task<IActionResult> RolesWithStaffs()
{
var model= await _context.Set<Staffs>().Include(s => s.Role).ToListAsync();
return View(model);
}
and view
<table class="table">
<thead>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Role
</th>
<th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(item=> item.FirstName)
</td>
<td>
#Html.DisplayFor(item=> item.LastName)
</td>
<td>
#Html.DisplayFor(item => item.Role.Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

How to Manipulate data to display appropriate html layout asp mvc

I come from a procedural PHP background. I am trying to learn how to do the same stuff I used to do in php and do it in asp.net. I need to sort my orders under their perspective Customer name.
Right now my layout is:
Sams Club
Order 1
Sams Club
Order 2
Walmart
Order 1
Walmart
Order 2
Walmart
Order 3
I need my layout more like:
Sams Club
Order 1
Order 2
Walmart
Order 1
Order 2
Order 3
I can easily do this with PHP but am struggling to figure out how to do this in an MVC type of application.
This is how my cshtml page looks.
<table class="table table-condensed" style="border-collapse:collapse;">
<thead>
<tr>
<th><input type="checkbox" name="CheckOrders" />Select All </th>
<th>Bill to Name</th>
<th>Qty Ordered</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr data-toggle="collapse" data-target="##Html.DisplayFor(model => item.customer_number)" class="accordion-toggle">
<td><input type="checkbox" name="checkAllCus" value="#Html.DisplayFor(model => item.customer_number)"/></td>
<td>
#Html.DisplayFor(model => item.Bill_to_Name)
</td>
<td>
#Html.DisplayFor(model => item.Quantity_Ordered)
</td>
</tr>
<tr>
<td colspan="12" class="hiddenRow">
<div class="accordian-body collapse" id="#Html.DisplayFor(model => item.customer_number)">
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>Order Number</th>
<th>Bill to Name</th>
<th>Qty Ordered</th>
<th>Ship Date</th>
<th>Item #</th>
<th>Description</th>
<th>State</th>
<th>Carrier</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="orders[]" value="#Html.DisplayFor(model => item.order_no)" /></td>
<td>
#Html.DisplayFor(model => item.order_no)
</td>
<td>
#Html.DisplayFor(model => item.Bill_to_Name)
</td>
<td>
#Html.DisplayFor(model => item.Quantity_Ordered)
</td>
<td>
#Html.DisplayFor(model => item.Ship_Date)
</td>
<td>
#Html.DisplayFor(model => item.item_no)
</td>
<td>
#Html.DisplayFor(model => item.descr1)
</td>
<td>
#Html.DisplayFor(model => item.shipstate)
</td>
<td>
#Html.DisplayFor(model => item.shipper)
</td>
<td>
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
}
</tbody>
</table>
Below is my Model
namespace OpenCustomerOrder3.Models
{
using System;
public partial class spOrderDetails_Result
{
public string cusNo;
public string customer_number { get; set; }
public string shipper { get; set; }
public string user_def_fld_5 { get; set; }
public string item_no { get; set; }
public string descr1 { get; set; }
public string location1 { get; set; }
public string Bill_to_Name { get; set; }
public Nullable<decimal> Quantity_Ordered { get; set; }
public string Requested_Date { get; set; }
public string Ship_Date { get; set; }
public string Status { get; set; }
public string order_no { get; set; }
public string shipstate { get; set; }
}
}
This really comes down to what your domain model looks like.
It looks like the model type being passed to the view at the moment is simply an IEnumerable<Order> or similar. If you really have to do this way, one way to achieve what you want is by grouping your orders by CustomerName using the GroupBy method in System.Linq.
However, a better model would be to let a Customer model have many orders, i.e. between Customer and Order there is a 1..* relationship. For example,
public class Customer
{
public string Name { get; set; }
public IEnumerable<Order> Orders { get; set; }
}
Then what you want is to pass an IEnumerable<Customer> instead to your view.

Using Checkbox in mvc

public class ProdList
{
public int ProdId { get; set; }
[DisplayName("Name")]
public string ProdName { get; set; }
[DisplayName("Price")]
public double? ProdPrice { get; set; }
[DisplayName("Description")]
public string ProdDesc { get; set; }
[DisplayName("Image")]
public string ImageVal { get; set; }
[DisplayName("Category Name")]
public string CateName { get; set; }
}
I have this class in my ProductListController. Using the following Action, I am populating my above class and passing it to the View.
public ActionResult ProdList()
{
Context con = new Context();
var prodlist = from p in con.Proddb join c in con.Catdb on p.CategoryID equals c.CategoryID select new ProdList() { ProdId=p.ProductID, ProdName = p.ProductName, ProdPrice = p.UnitPrice, ProdDesc=p.Description, CateName=c.CategoryName, ImageVal= "~/Image/"+p.ImagePath };
List<ProdList> prodlst = prodlist.ToList<ProdList>();
var categories = con.Catdb.ToList<Category>();
ViewBag.Categories = categories;
return View("ProdListView", prodlst);
}
My ProdListView includes the following list where I am printing the data:
#using (Html.BeginForm("checkboxhandle", "ProductList"))
{
#Html.AntiForgeryToken()
<table class="table table-condensed" id="prodtbl">
<tr>
<th>
#Html.DisplayNameFor(model => model.ImageVal)
</th>
<th>
#Html.DisplayNameFor(model => model.ProdName)
</th>
<th>
#Html.DisplayNameFor(model => model.ProdPrice)
</th>
<th>
#Html.DisplayNameFor(model => model.ProdDesc)
</th>
<th>
#Html.DisplayNameFor(model => model.CateName)
</th>
<th>
Check to Add
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
<img src="#Url.Content(#Html.DisplayFor(modelItem => item.ImageVal).ToString())" height="150" width="150">
</td>
<td>
#Html.DisplayFor(modelItem => item.ProdName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProdPrice)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProdDesc)
</td>
<td>
#Html.DisplayFor(modelItem => item.CateName)
</td>
<td>
#*Checkbox*#
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ProdId }) |
#Html.ActionLink("Details", "Details", new { id = item.ProdId }) |
</td>
</tr>
}
</table>
<div class="form-group" style="text-align:center">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Add to the Cart" class="btn btn-default" />
</div>
</div>
}
Following is the action method I am invoking once the submit button is clicked.
[HttpPost]
public ActionResult checkboxhandle(ProdList pdl)
{
/*Logic to get the checked items from the list in the view*/
}
I tried various methods to include checkbox and retrieve the checked items back in my controller but it didn't help. I'm really confused how to proceed. Please help me.
First of all add a bool property to your model/viewmodel:
public bool SelectedProduct {get;set;}
and then you need to do a for loop for the List<T>, so that model binder could populate items back when form posted like:
#for(int i=0; i< Model.Count; i++)
{
<tr>
<td>
<img src="#Url.Content(#Html.DisplayFor(modelItem => Model[i].ImageVal).ToString())" height="150" width="150">
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].ProdName)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].ProdPrice)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].ProdDesc)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].CateName)
</td>
<td>
#Html.CheckBoxFor(modelItem => Model[i].SelectedProduct)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = Model[i].ProdId }) |
#Html.ActionLink("Details", "Details", new { id = Model[i].ProdId }) |
</td>
</tr>
}

MVC Model binding on multiple edit

I have the following view model
public class ResourceProjectedCapacitiesModel
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Location { get; set; }
public string Manager { get; set; }
public string Role { get; set; }
public string Project { get; set; }
public decimal Capacity { get; set; }
public System.DateTime Date { get; set; }
}
In my GET action i display all these in the view.
[HttpPost]
public ActionResult Index(List ResourceProjectedCapacitiesModel> list)
{
foreach (ResourceProjectedCapacitiesModel item in list)
{
....
}
....
}
In the view there is the following editor but when the form is submitted the binding doesnt work, list is null
#Html.EditorFor(modelItem => item.Capacity)
#Html.HiddenFor(modelItem => item.ID)
#model List<CapacityPlanner.ViewModels.ResourceProjectedCapacitiesModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using(Html.BeginForm())
{
<table class="table">
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Location
</th>
<th>
Manager
</th>
<th>
Role
</th>
<th>
Project
</th>
<th>Apr</th>
<th>May</th>
<th>Jun</th>
<th>Jul</th>
<th>Aug</th>
<th>Sep</th>
<th>Oct</th>
<th>Nov</th>
<th>Dec</th>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Location)
</td>
<td>
#Html.DisplayFor(modelItem => item.Manager)
</td>
<td>
#Html.DisplayFor(modelItem => item.Role)
</td>
<td>
#Html.DisplayFor(modelItem => item.Project)
</td>
#for(var i = 1; i <= 12; i++)
{
<td>
#if(item.Date.Month == i)
{
#Html.EditorFor(modelItem => item.Capacity)
}
</td>
}
<td>
#Html.HiddenFor(modelItem => item.ID)
</td>
</tr>
}
</table>
<input type="submit" value="Save" class="btn btn-default" />
}
I have inserted the code of my view
You should use for instead of foreach.
#for (int i = 0; i < Model.Items.Count; i++)
{
#Html.EditorFor(model => Model.Items[i].Amount)
#Html.HiddenFor(model => Model.Items[i].Amount)
}
Then all filled will get different id.

Categories