ASP MVC passing model data in view back as form data - c#

I got the following Razor view that display a list of HDD so an user and add to a cart. When the user press the button next to each row of HDD, it will pass the quantity and HDD's identity to a controller. However, while each HDD's ID does display properly, "hddId" is always 1 and "quantity" is correctly 5 when I inspect the Controller's parameters.
#model IEnumerable<TestStore.Models.Hdd>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using(Html.BeginForm("AddToCart","Cart")){
<table>
<tr>
<th>
Ident
</th>
<th>
Brand
</th>
<th>
Name
</th>
<th>
Model
</th>
<th>
Speed
</th>
<th>
Capacity
</th>
<th>
Cache
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.hddId)
</td>
<td>
#Html.Hidden("hddId", item.hddId)
#Html.Hidden("quantity", 5)
#Html.DisplayFor(modelItem => item.brand)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.model)
</td>
<td>
#Html.DisplayFor(modelItem => item.speed)
</td>
<td>
#Html.DisplayFor(modelItem => item.capacity)
</td>
<td>
#Html.DisplayFor(modelItem => item.cache)
</td>
<td>
<input type="submit" value="Add to Cart" />
</td>
</tr>
}
</table>
}

Codingbiz is correct. The submit button wasn't referring to any particular row but the entire table. I suspect the reason why "hddId" was always "1" is because that's the first reference of "hddId" it see when the form is submitted. I changed it so #using(Html.BeginForm(...)) is inside the #foreach loop so each row has its own form and submit button:
#foreach (var item in Model) {
<tr>
#using(Html.BeginForm("AddToCart","Cart")){
<td>
#Html.DisplayFor(modelItem => item.hddId)
</td>
<td>
#Html.Hidden("hddId", item.hddId)
#Html.Hidden("quantity", 5)
#Html.DisplayFor(modelItem => item.brand)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.model)
</td>
<td>
#Html.DisplayFor(modelItem => item.speed)
</td>
<td>
#Html.DisplayFor(modelItem => item.capacity)
</td>
<td>
#Html.DisplayFor(modelItem => item.cache)
</td>
<td>
<input type="submit" value="Add to Cart" />
</td>
}
</tr>
}

As others have said, this doesn't work because when you submit, you're submitting every row in the table, not just the one clicked.
One option is to do what they suggest in this article:
http://federmanscripts.com/2010/01/12/form-and-table-row-nesting-workaround/
That is, using javascript, you copy the form values on button press to a hidden row and submit that.

I got around the validation problem by using button type="submit" instead of input type="submit". It still works correctly by passing the id number to the controller.
#using(Html.BeginForm("AddToCart","Cart")){
<table>
<tr>
//header stuff here
</tr>
#foreach (var item in Model) {
//row data goes here
//remove hidden field reference to #item.hddId
<tr>
<td>
<button type="submit" value="#item.hddId" name="hddId">Add to Cart</button>
</td>
</tr>
</table>
}

Related

How do I post the row id in a custom built ASP.NET Core Razor Pages editable Grid?

I have tried several approaches, and as I'm new to Razor Pages in ASP.NET Core I'm blocked. Could anybody help me please? It must be something trivial but I googled quite a lot and I can't find a suitable way. I don't want to use jquery or any other javascript library.
Here is the relevant code:
<form method="post">
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.GridRows)
{
<tr>
<td>
<input type="hidden" asp-for="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
}
</tbody>
</table>
</form>
public async Task<IActionResult> OnPostAsync(int id)
{
if (!ModelState.IsValid)
{
return Page();
}
var gridRowUpdate = await _context.GridRows.FindAsync(id);
if (gridRowUpdate == null)
{
return NotFound();
}
if(await TryUpdateModelAsync<GridRow>(gridRowUpdate, "GridRow", g => g.Text1, g => g.Text2, g => g.Text3))
{
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
IF you want to click each save button to send the Id of that row, You can just follow below simple demo without any jquery or any other javascript library.
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.test)
{
<form method="post" >
<tr>
<td>
<input type="hidden" name="Id" value="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
</form>
}
</tbody>
</table>

Passing IEnumerable EditorFor value through ActionLink to the Action

So, I am new to MVC, and I have a partial view with IEnumerable model, in which I have few fields I would like to be editable.
#model IEnumerable<Allocations>
<p>
#Html.ActionLink("Create New", "AddAllocation", "Admin")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Percentage)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.EditorFor(modelItem => item.Percentage)
</td>
<td>#Html.HiddenFor(modelItem => item.ID)</td>
<td>
#Html.ActionLink("Save", "EditAllocation", "Admin", null, new { id= item.ID })
</td>
</tr>
}
</table>
I want to be able to pass the entered/changed textbox values to the controller action. I understand, I can do that using JQuery if it wasn't a IEnumerable model view. I might be missing something here, and would appreciate if someone could direct me in the right direction.

Find the value of a <TD> and retrive it into input box

I have some trouble to get the text in a and put it in an Box, here you can find a small example.
The idea is when the user click the "Select" it put the code from inside the
<td> #Html.DisplayFor(Mod => Item.Item.Custumer_code) <td/>
in the Input input with the Custumercode ID.
here is the code:
<div class="col-sm-3">
<input class="form-control"
placeholder="Entre a custumer code"
id="Custumercode"
name="Custumercode"/>
</div>
<table class="table">
<thead>
<tr>
<th>Costumer Code</th>
<th>Select</th>
<th>Costumer Name</th>
<th>Email </th>
<th>Tel </th>
</tr>
</thead>
#foreach (var Item in Model)
{
<tbody>
<tr>
<td> #Html.DisplayFor(Mod => Item.Custumer_code) </td>
<td> #Html.DisplayFor(Mod => Item.custumer_name) </td>
<td> #Html.DisplayFor(Mod => Item.Email) </td>
<td> #Html.DisplayFor(Mod => Item.Tel) </td>
<td>
<button type="button" class="btn" onclick="myFunction()">
Select
</button>
</td>
</tr>
</tbody>
}
</table>`
Try this
$(document).ready(function(){
$(document).on('click','.btn',function(){
var customer = $(this).parents('tr').find('td:eq(0)').text();
$('#Custumercode').val(customer );
});
});
DEMO
Try this:
$(document).ready(function(){
$('.btn').click(function(){
var customerCode = $(this).closest('tr').find('td:nth-child(1)').text();
$('#Custumercode').val(customerCode );
});
});

ASP.NET MVC Complex Model Updating

I have a PersonViewModel that consists of several List<SubViewModel> (Name, Address, etc.)
I have an Html Form with tables for each SubViewModel, where the user can update,add,delete and set items to the primary entry for the person.
a simplified table for names:
#foreach (PersonNameViewModel name in Model.Names)
{
<tr>
<td>
#Html.DisplayFor(modelItem => name.FullName)
</td>
<td>
#Html.DisplayFor(modelItem => name.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => name.MiddleName)
</td>
<td>
#Html.DisplayFor(modelItem => name.LastName)
</td>
<td class="center">
#Html.RadioButtonFor(modelItem => name.IsPrimary, "")
</td>
<td class="center">
#Html.CheckBoxFor(modelItem => name.ToDelete)
</td>
</tr>
}
From here, I don't know how to get all the data back into the PersonViewModel when the user submits the form, to update the person record. If I simply accept a PersonViewModel in my POST controller, it's completely empty. I looked at FormCollection, but I'm not sure if that's right for this. Can someone with experience point me in the right direction for building my model back up for updating? Thankyou very much.
Everyone's answer is correct, But if you want to update people's information, you need to use Html Helper Editor NOT Display. Also, you still can use foreach in your view, just change it like below:
#foreach (var name in Model.Names.Select((value, i) => new { i, value }))
{
<tr>
<td>
#Html.EditorFor(m => m.Names[#name.i].FullName)
</td>
<td>
#Html.EditorFor(m => m.Names[#name.i].FirstName)
</td>
<td>
#Html.EditorFor(m => m.Names[#name.i].MiddleName)
</td>
<td>
#Html.EditorFor(m => m.Names[#name.i].LastName)
</td>
<td class="center">
#Html.RadioButtonFor(m => m.Names[#name.i].IsPrimary,"")
</td>
<td class="center">
#Html.CheckBoxFor(m => m.Names[#name.i].ToDelete)
</td>
</tr>
}
You should use sth like this (good article about model binding of collections and complex data here):
#for(var i = 0;i < Model.Names.Count;i++)
{
<tr>
<td>
#Html.DisplayFor(m => Model.Names[i].FullName)
</td>
<td>
#Html.DisplayFor(m => Model.Names[i].FirstName)
</td>
<td>
#Html.DisplayFor(m => Model.Names[i].MiddleName)
</td>
<td>
#Html.DisplayFor(m => Model.Names[i].LastName)
</td>
<td class="center">
#Html.RadioButtonFor(m => Model.Names[i].IsPrimary, "")
</td>
<td class="center">
#Html.CheckBoxFor(m => Model.Names[i].ToDelete)
</td>
</tr>
}
Try replacing the foreach with a for loop:
#for (int i = 0; i < Model.Names.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(m => m.Names[i].FullName)
</td>
<td>
#Html.DisplayFor(m => m.Names[i].FirstName)
</td>
<td>
#Html.DisplayFor(m => m.Names[i].MiddleName)
</td>
<td>
#Html.DisplayFor(m => m.Names[i].LastName)
</td>
<td class="center">
#Html.RadioButtonFor(m => m.Names[i].IsPrimary, "")
</td>
<td class="center">
#Html.CheckBoxFor(m => m.Names[i].ToDelete)
</td>
</tr>
}
The expression parsing/model binding does a better job with indexes than with foreach temp variables.

How do i show a list from a model to another View in ASP.NET MVC 4

I have a list of Topic's. Each Topic have a list of Message. When i click on "Details" I want to open a new View that display a list of the Message's from the Topic.
I expect that I need to modify this line: (this is what I have so far)
#Html.ActionLink("Details", "Details", new { id=item.Id }, null)
The Message's are accessed by item.Message.
And the first line in the Detail View
#model IEnumerable<Models.TopicMessage>
This is my Topic View:
#model IEnumerable<Models.Topic>
<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("Details", "Details", new { id=item.Id }, null)
</td>
</tr>
}
</table>
There are a number of ways to do that. You can use the Action method to execute the controller action directly:
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.Action("Details", "Details", new { id=item.Id })
</td>
</tr>
Or you can bypass the controller and render the view directly using this overload of DisplayFor:
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Messages, "MessagesDetail")
</td>
</tr>
Or if you define the template as the default DisplayTemplate, you can just do this:
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Messages)
</td>
</tr>
I fixed this by making a somethingViewModel that contained both the liste and the Id. That way i could contain the two information from two difference places in one new object I had access to in the View.

Categories

Resources