Post collection of selected values to server action - asp.net-mvc

I have a form with a product-warranty list.
Each list item has checkbox.
How can I post a list of SelectecSources (warranties) to the server?
What do I have to change in that code?
The WarrantyPlusViewModel object is posted to the server. It contains a list SelectedSources which should contain the selected warranty articles.
Is it possible at all to use a complex object for the selected list?
Consider I have to post the WarrantyPlusViewModel to the server which includes
the SelectedSources property with the selected warranty objects.
#model WarrantyPlusViewModel
<div class="row">
<div class="col-md-10 col-md-offset-1">
#using (...)
{
<table class="table table-striped">
<tr>
<th></th>
<th>#Html.DisplayFor(m => m.ProductSelected.Name)</th>
<th>#Html.DisplayFor(m => m.ProductSelected.Description,l)</th>
<th>#Html.DisplayFor(m => m.ProductSelected.Price)</th>
</tr>
#foreach (var product in Model.ProductList)
{
<tr>
<td><input type="checkbox" name="SelectedSources" value="#product" /></td>
<td>#product.Name</td>
<td>#product.Description</td>
<td>#product.Price</td>
</tr>
}
</table>
<input type="submit" value="Save" />
#Html.HiddenFor(p => p.SerialNumber)
}
</div>
[HttpPost]
public virtual async Task<ActionResult> Save(WarrantyPlusViewModel viewModel)
{
return View(MVC.WarrantyPlus.WarrantyPlus.Views.OverviewWarrentyPlus, viewModel);
}
public class WarrantyPlusViewModel
{
// other properties
public List<WarrantyPlusProductViewModel> ProductList { get; set; }
public IEnumerable<WarrantyPlusProductViewModel> SelectedSources { get; set; }
}

It's really hard to bind this way. If you want to do it you should override Model Binder.
If i were on your place i will just use ProductId with some knowlege of list binding and come up with this solution:
#for (var i = 0; i < Model.ProductList.Count(); i++)
{
<tr>
<td><input type="checkbox" name="ProductList[" #i "].Id" value="#Model.ProductList[i].Id" /></td>
<td>#Model.ProductList[i].Name</td>
<td>#Model.ProductList[i].Description</td>
<td>#Model.ProductList[i].Price</td>
</tr>
}

Related

Send table from view to action in MVC application

I am looking for a way to send a table of data from view to action in .net core mvc. There are tones of explanations about sending data from action to a view using razor foreach and for loops but how to do the opposite using model binding?
I know/used ajax to send data of this sort but data binding is much easier to implement. Also due to lack of answers that I have found in few hours of searching I am starting to believe that I am missing something. I probably did not understand a basic concept of data binding.
Lets say I have a simple model like so:
public class myMode
{
public string item1 { get; set; }
public string item2 { get; set; }
}
Then the view model will be:
public class MyViewModel
{
public List<myMode> tableData { get; set; }
}
In the view I can use something like:
<table>
<tr>
<th>Item1</th>
<th>Item2</th>
</tr>
foreach (var d in Model.tableData)
{
<tr>
<td>#d.item1</td>
<td>#d.item2</td>
</tr>
}
</table>
This is how to get the data from view model to the table. How to do the opposite?
Lets say that in the same example the user is adding rows to the table. How can we bind the table rows to view model List<myMode> tableData { get; set; } when form is submited?
How can we bind the table rows to view model List tableData {
get; set; } when form is submited?
We can use name="tableData[#i].item1" to bind the table rows to view model List tableData
They generate the html like :
You can try the below code:
#model MyViewModel
<form asp-action="Index">
<table>
<tr>
<th>Item1</th>
<th>Item2</th>
</tr>
#{
int i = 0;
}
#foreach (var d in Model.tableData)
{
<tr>
<td><input name="tableData[#i].item1" /></td>
<td><input name="tableData[#i].item2" /></td>
</tr> #(i++)
}
</table>
<input type="submit" />
</form>
Controller:
[HttpPost]
public IActionResult Index(MyViewModel MyViewModel)
{
return View(MyViewModel);
}
result:
If you want to show the data at the table, then submit it, you can try:
<tr>
<td><input asp-for="#Model.tableData[i].item1" /></td>
<td><input asp-for="#Model.tableData[i].item2" /></td>
</tr>
<form asp-action="Privacy">
<table>
<tr>
<th>Item1</th>
<th>Item2</th>
</tr>
#{ int i = 0;}
#foreach (var d in Model.tableData)
{
<tr>
<td><input asp-for="#Model.tableData[i].item1" value="#d.item1"/></td>
<td><input asp-for="#Model.tableData[i].item2" value="#d.item2"/></td>
</tr>
#(i++)
}
</table>
<input type="submit" />
</form>

ASP.NET MVC CheckBox List sending always null

I want to create a table with items and checkboxes to select these items. I am including these checkboxes in a list but this list is always returning null. Thank you very much for your help.
Controller:
public ActionResult Index()
{
var expenseTypesView = new ViewExpenseTypesAndSelection
{
ExpensesTypes = _context.ExpenseType.ToList(),
};
return View(expenseTypesView);
}
[HttpPost]
public ActionResult SelectExpensesTypes( ViewExpenseTypesAndSelection SelectedExpenses)
{
var entry = new userSpecificExpenses();
var i = 0;
foreach (var item in SelectedExpenses.SelectedExpenses)
{
if(item)
{
entry.expenseTypeId = i;
entry.UtilisateurId= User.Identity.GetUserId();
_context.UserspecificExpenses.Add(entry);
_context.SaveChanges();
}
i++;
}
return View();
}
View:
#model MBT.ViewModels.ViewExpenseTypesAndSelection
....
#using (Html.BeginForm("SelectExpensesTypes", "ExpenseTypes"))
{
<table class="table table-bordered table-hover">
<thead>
<tr>
<th class="text-center">Expense</th>
<th class="text-center">Include</th>
</tr>
</thead>
<tbody>
#{
for (int i = 0; i < Model.ExpensesTypes.Count; i++)
{
<tr>
<td>
<div class="checkbox">
#Model.ExpensesTypes[i].Type
</div>
</td>
<td>
<div class="checkbox">
#Html.CheckBoxFor(m => m.SelectedExpenses[i])
</div>
</td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-primary">Submit</button>
}
You sending ViewExpenseTypesAndSelection almost null just with ExpensesTypes and then post it back to your post method. It means you send null and receive null.
So what is wrong with that?

Posted model is null

I'm not sure what's wrong since I'm very new with MVC. This is a shopping cart. The customer is able to review their cart and edit quantity.
On the HttpPost ViewCart method, the cart is always empty, and number of lines is zero.
Controller:
public ActionResult ViewCart() {
var cart = (CartViewModel)Session["Cart"];
return View(cart);
}
[HttpPost]
public ActionResult ViewCart(CartViewModel cart) {
Session["Cart"] = cart;
return RedirectToAction("Order", "Checkout");
}
View:
#model CartViewModel
using (Html.BeginForm()) {
<h2>Your cart</h2>
<table>
<thead> ... </thead>
<tbody>
#foreach (var item in Model.Lines) {
<tr>
<td>#Html.DisplayFor(modelItem => item.Article.Description)</td>
<td>#Html.EditorFor(modelItem => item.Quantity)</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="Checkout">
}
ViewModel:
public class CartViewModel {
public List<Line> Lines { get; set; }
public CartViewModel() {
Lines = new List<Line>();
}
}
Try changing the view to use indexes:
#model CartViewModel
using (Html.BeginForm()) {
<h2>Your cart</h2>
<table>
<thead> ... </thead>
<tbody>
#for (int i = 0; i < Model.Lines.Count; i++) {
<tr>
<td>#Html.DisplayFor(m => Model.Lines[i].Article.Description) #Html.HiddenFor(m => Model.Lines[i].Article.Id)</td>
<td>#Html.EditorFor(m => Model.Lines[i].Quantity)</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="Checkout">
}

Passing entire Model from a View back to the Controller

I got a list of:
public class Items
{
public String Nro_Item { get; set; }
public Sucursal Sucursal { get; set; }
public Areas Area { get; set; }
public Sectores Sector { get; set; }
public bool ID_Estado { get; set; }
}
I'm passing it to this view:
#using ClientDependency.Core.Mvc
#model IEnumerable<TrackingOperaciones.Controllers.Items>
#{
ViewBag.Title = "Ver Items";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br/>
#using (Html.BeginForm("CargarRecibidos", "Recepcion", FormMethod.Post))
{
<table class="table table-striped table-bordered table-condensed">
<tr>
<th>
Numero
</th>
<th>
Sucursal
</th>
<th>
Area
</th>
<th>
Sector
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.ID_Estado)
</td>
</tr>
}
</table>
<p>
<input class="btn" name="Guardar" type="submit" value="Guardar"/> |
#Html.ActionLink("Volver al listado de RecepciĆ³n", "Index")
</p>
}
Until there everything is fine: Now the problem is getting back the entire model with the checked values in a controller for processing it like this one:
[HttpPost]
public ActionResult CargarRecibidos(IEnumerable<Items> items)
{
if (ModelState.IsValid)
{
//do something here
}
return RedirectToAction("Index");
}
}
But i'm falling miserably because "items" came back empty in the postback
i'm guess something is wrong with the form
#using (Html.BeginForm("CargarRecibidos", "Recepcion"))
{
<input class="btn" name="Guardar" type="submit" value="Guardar"/>
}
please help me!
Use IEnumerable
Then the controller input parameter will be List
Perhaps also consider using AJAX POST with JSON objects in place of a form submit (more modern/elegant) but submits are fine too.
Part of the problem is it won't post the entire model since only the checkbox is a form value. I think you need to add an additional hidden value in your form to track the item number and then handle the checkbox values specially in the controller. The item number is appended to "checkbox" in the posted values to keep them distinct.
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
#Html.Hidden("Nro_Item", item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBox("checkbox" + item.Nro_Item, item.ID_Estado)
</td>
</tr>
In the controller only bind to the number item so it can be used to process the checkboxes:
[HttpPost]
public ActionResult CargarRecibidos(List<string> nro_item)
{
foreach (string item in nro_item)
{
var checkbox=Request.Form["checkbox" + item];
if (checkbox != "false") // if not false then true,false is returned
{
// Do the action for true...
}
else
{
// Do the action for false
}
}
return View();
}

How to bind a List of ViewModel in ASP MVC?

Does anyone know how to get POST values for MODELVIEW Pattern below. I can display the MenuItem as Checkboxes and Radio buttons,
but when user submits the form i.e. POST, ModelViewTest is null. I'm expecting List of MenuItems that user have selected.
public class ModelViewTest
{
public IEnumerable<MenuItem> MenuItemList { get; set; } //Will be displayed as listboxes and checkboxes
public Restaurant restaurant {get;set;}
}
ACTIONS:
public ActionResult Edit()
{
//some code here
}
return View(new ModelViewTest());
}
[HttpPost]
public ActionResult Edit(ModelViewTest model)
{
//I'm not getting List of MenuItems
return View();
}
MenuItem Class:
public class MenuItem
{
public string MenuItemCode{get;set;}
public string MenuItemDescription{get;set;}
public string UIType {get;set;} //This determines whether it's radio or checkbox
public string UIGroupType {get;set;} //Determines the Group for radio/checkbox.
}
public class Restaurant
{
public string restaurantName{get;set;}
public MenuItem MenuItem{get;set;}
}
Update
Please see my View code snippet below:
<table>
#foreach (var menu in Model.MenuList)
{
if (menu.UIType == "Radio")
{
<tr>
<td align="left">
<input id="MenuCheckboxRadio" name="#Menus.UIGroup" value="#Menu.MenuItemCode" type="radio" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
else
{
<tr>
<td align="left">
<input id="MenuCheckbox" name="#Menus.UIGroup" value="#Menus.#MenuItem" type="checkbox" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
i++;
}
</table>
In order to get the list of menu items in the POST action you need their corresponding values must be included in the html <form> and because this is a collection follow the standard naming convention so that the default model binder can parse them.
First you should show us your view to know how you render your ViewModel.
However try this:
make partial view to be editor template for your MenyItem
<%# Control Inherits="ViewUserControl<MenyItem>" %>
<%: Html.TextBoxFor(m => m.MenuItemCode) %>
<%: Html.TextBoxFor(m => m.MenuItemDescription) %>
.......
then in your view make for loop NOT foreach:
<%# Page Inherits="ViewPage<ModelViewTest>" %>
<% using (Html.BeginForm()) {%>
<% for (int i = 0; i < 3; i++) { %>
<%: Html.EditorFor(m => m.MenuItemList[i]) %>
<% } %>
<% } %>
And please see this answer
Please see my View code snippet below:
<table>
#foreach (var menu in Model.MenuList)
{
if (menu.UIType == "Radio")
{
<tr>
<td align="left">
<input id="MenuCheckboxRadio" name="#Menus.UIGroup" value="#Menu.MenuItemCode" type="radio" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
else
{
<tr>
<td align="left">
<input id="MenuCheckbox" name="#Menus.UIGroup" value="#Menus.#MenuItem" type="checkbox" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
i++;
}
</table>

Resources