ASP.NET MVC4 FormCollection.GetValues not returning correct values - asp.net-mvc

I'm building a mobile webiste using ASP.NET MVC4.
One of the pages in my solution contains a table where all the rows in the table can be edited and saved in one batch. To do this I am using FormCollection in the Action in the Controller. This works as expected for most of the fields, exept one: item.IsPercent. This field is a boolean, and FormCollection.GetValues("item.IsPercent") returns twice the number of rows in the table and the list always alternates between true and false, no matter what the actual values are.
How can I collect the right value for the Percent checkboxes?
An Example
My View
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
foreach (var group in Model.GroupBy(i => i.Exercise.Name)) {
<table>
<tr>
<th colspan="4">#Html.Label(group.Key)</th>
</tr>
<tr>
<td>Load</td>
<td>Percent</td>
<td> </td>
<td>Reps</td>
</tr>
#foreach (var item in group.OrderBy(i => i.Order))
{
#Html.HiddenFor(modelItem => item.Id)
<tr>
<td>
#Html.EditorFor(modelItem => item.Load)
#Html.ValidationMessageFor(modelItem => item.Load)
</td>
<td>
#Html.EditorFor(modelItem => item.IsPercent)
</td>
<td>
x
</td>
<td>
#Html.EditorFor(modelItem => item.Repetitions)
#Html.ValidationMessageFor(modelItem => item.Repetitions)
</td>
</tr>
}
</table>
<br />
}
<p>
<input type="submit" value="Save" />
</p>
}
My Controller
[HttpPost]
public ActionResult EditProgramTemplateLines(FormCollection c)
{
int i = 0;
int ptId = 0;
if (ModelState.IsValid)
{
var ptIdArray = c.GetValues("item.id"); // [1,2,3,4]
var ptLoadArray = c.GetValues("item.Load"); // [50, 55, 60, 80]
var ptPercentArray = c.GetValues("item.IsPercent"); // [true, false, true, false, true, false, true, false]
var ptRepsArray = c.GetValues("item.Repetitions"); // [13, 10, 5, 2]
for (i = 0; i < ptIdArray.Count(); i++) {
var ptLine = factory.GetProgramTemplateLine(Convert.ToInt32(ptIdArray[i]));
if(ptId == 0)
ptId = ptLine.ProgramTemplateId;
ptLine.Load = ConvertToDouble(ptLoadArray[i]);
ptLine.IsPercent = Convert.ToBoolean(ptPercentArray[i]);
ptLine.Repetitions = ConvertToInt(ptRepsArray[i]);
factory.SetEntryAsModified(ptLine);
}
factory.SaveChanges();
return RedirectToAction("Details", new { id = ptId });
}
return View();
}
Updated solution
Considering the link posted in comment below FormCollection for a checkbox my solution is to loop throug the array like this:
var percentId = 0;
for(i = 0;i<ptIdArray.Count();i++){
if(ptPercentArray[percentId] == true){
item.IsPercent = true;
percentId = percentId + 2;
}
else{
item.IsPercent = false;
percentId++;
}
}

Take a look at the HTML generated for the Html.EditorFor! The helpers create one checkbox and one hidden field for each checkbox to make state management easily at server side! Thats the problem! Using FormCollection as parameter you need to differentiate the hidden from the real checkbox to get the value!
Hopes this help you!

Related

My ASP.NET MVC index table looks very weird - columns are not showing up and others are under the wrong heading. Why?

I'm building one of my first projects in ASP.NET MVC and EF. Everything else has worked well so far but I'm flummoxed at how the below table is coming out. The first column (Item) is correct, but the Product is not showing up (it's populated, I checked) and the CRUD column is supposed to show those three buttons, which instead appear off the right side of the table. It's probably something really really REALLY stupid that I'm overlooking but I can't see what.
Here is the code from my index view. If you need me to post other pieces tell me what, I don't want to post all sorts of unnecessary code here to make it too complex.
The
"#Html.Partial("_TableButtonsPartial",
new SmallButtonModel
{ ItemID = item.ItemID, ProductID = item.ProductID }"
is the code for those three buttons. They function like they should, they're just offset.
#model IEnumerable<Memberships.Areas.Admin.Models.ProductItemModel>
#using Memberships.Extensions
#using Memberships.Areas.Admin.Models;
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.Partial("_CreateButtonPartial")
</p>
<table class="table table-condensed table-striped">
<tr class="success">
<th>#Html.DisplayNameFor(model => model.ItemTitle)</th>
<th>#Html.DisplayNameFor(model => model.ProductTitle)</th>
<th>CRUD</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td> #Html.DisplayFor(modelItem => item.ItemTitle)</td>
<td> #Html.DisplayFor(modelItem => item.ProductTitle) </td>
<td>
#Html.Partial("_TableButtonsPartial",
new SmallButtonModel
{ ItemID = item.ItemID, ProductID = item.ProductID })
</td>
</tr>
}
</table>
enter code here
EDIT: Added code from _TableButtonsPartial partial view.
#model Memberships.Areas.Admin.Models.SmallButtonModel
#using Memberships.Areas.Admin.Models;
#*Now it's time to build the tiny buttons from SmallButtonModel into a row that can be displayed on an index page.*#
<td style="width:120px;">
<div class="btn-group" role="group">
#Html.Partial("_SmallButtonPartial",
new SmallButtonModel
{
Action = "Edit",
ButtonType = "btn-primary",
Glyph = "pencil",
Text = "Edit Button",
ID = Model.ID,
ItemID = Model.ItemID,
ProductID = Model.ProductID,
SubscriptionID = Model.SubscriptionID
})
#Html.Partial("_SmallButtonPartial",
new SmallButtonModel
{
Action = "Details",
ButtonType = "btn-success",
Glyph = "list",
Text = "Detail Button",
ID = Model.ID,
ItemID = Model.ItemID,
ProductID = Model.ProductID,
SubscriptionID = Model.SubscriptionID
})
#Html.Partial("_SmallButtonPartial",
new SmallButtonModel
{
Action = "Delete",
ButtonType = "btn-danger",
Glyph = "trash",
Text = "Delete Button",
ID = Model.ID,
ItemID = Model.ItemID,
ProductID = Model.ProductID,
SubscriptionID = Model.SubscriptionID
})
</div>
</td>

How to calculate total value from razor view with javascript? MVC project

I got a .Net project using MVC and Razor.
I pass to the view a list containing products, where I have ProdutoValor( product value) with a TextboxFor for QuantidaVenda (Number os itens sold) for each iten. I want to get the value "QuantidadeVenda * ProdutoValor" for each item and show in a textbox the total value. How can I manage to do that with javascript?
I wanto to calculate the total as soon as the user enters the quantity
here is my view :
#for (int i = 0; i < Model.Produtos.Count; i++)
{
<tr>
<td>
#Html.HiddenFor(model => model.Produtos[i].ProdutoId)
#Html.HiddenFor(model => model.Produtos[i].ProdutoDescricao)
#Html.DisplayFor(model => model.Produtos[i].ProdutoNome)#Html.HiddenFor(model => model.Produtos[i].ProdutoNome)
</td>
<td>
#Html.DisplayFor(p => p.Produtos[i].ProdutoValor, new { #class = "form-control", Value = Model.Produtos[i].ProdutoValor }) #Html.HiddenFor(model => model.Produtos[i].ProdutoValor)
</td>
<td>
#Html.DisplayFor(p => p.Produtos[i].ProdutoEstoque, new { #class = "form-control", Value = Model.Produtos[i].ProdutoEstoque })#Html.HiddenFor(model => model.Produtos[i].ProdutoEstoque)
</td>
<td>
#if (Model.Produtos[i].ProdutoEstoque < 1)
{
#Html.TextBoxFor(p => p.Produtos[i].QuantidadeVenda, new { value = 0, disabled = "disabled" })
}
else
{
#Html.TextBoxFor(p => p.Produtos[i].QuantidadeVenda, new { value = 0, #id = "quantidade" })
if (Model.Produtos[i].ProdutoEstoque < Model.Produtos[i].QuantidadeVenda)
{<p>valor invalido</p>}
}
</td>
</tr>
}
[enter image description here][1]
how the list looks like
For Javascript:
Onchange Event for QuantidadeVenda(quantity):
function onchange()
{
var total= document.getElementById("name of total textbox").Value*
document.getElementById("name of quantity textbox").value
document.getElementById("name of total textbox").innerHTML=total
}
Jquery:
on change or LostFocus Event
$("input").change(function(){
var total= $("#name of total textbox").val()*
$("#name of quantity textbox").val()
$("#name of total textbox").val=total
});
Updated Code
HTML:
<table border="1">
<tr>
<td>product</td>
<td>quantity</td>
<td>total</td>
</tr>
<tr>
<td>
10
</td>
<td>
<input type="text" name="txt" value="" onchange="myFunction(this)">
</td>
<td><label>_</label></td>
</tr>
<tr>
<td>
10
</td>
<td>
<input type="text" name="txt" value="" onchange="myFunction(this)">
</td>
<td><label>_</label></td>
</tr>
</table>
Javascript:
function myFunction($this) {
debugger $($this).parent().siblings(":last").find('label').text($($this).parent().siblings().first().text().trim() * $this.value)
}

error while posting pagedlist from view to the controller

I've an indexed page in MVC with data that displays in a table format from the database and using paging. I want to edit only one column of the table. Can I post the paging list to the controller for editing. If so how?
I'm able to edit with normal list getting error while passing PagedList
--- this is my index page----
#model PagedList.IPagedList<emp_prac.Models.Employee>
#using PagedList.Mvc;
#*#model List<emp_prac.Models.Employee>*#
#using (Html.BeginForm("UpdateOrder", "Employee", FormMethod.Post))
{
Html.AntiForgeryToken();
Html.EditorForModel();
ViewBag.Title = "Employee Details";
<h2>Employee Details</h2>
<p>
#Html.ActionLink("Create New", "InsertEmployee")
</p>
<table class="table">
<thead>
<tr>
<th>Edit</th>
<th>Delete</th>
<th>Name</th>
<th>Email</th>
<th>Phone No</th>
<th>Salary</th>
<th>Joining Date</th>
<th>PDF</th>
<th>Status</th>
<th>Order</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Html.ActionLink("Edit", "EditEmployee", new { id = Model[i].emp_id }) </td>
<td>#Html.ActionLink("Delete", "DeleteEmployee", new { id = Model[i].emp_id }, new { onclick = "return confirm('Are you sure you want to delete?');", #class = "btn-btn-default" }) </td>
<td>#Html.DisplayFor(model => model[i].emp_name)</td>
<td>#Html.DisplayFor(model => model[i].emp_email)</td>
<td>#Html.DisplayFor(model => model[i].emp_phone_no)</td>
<td>#Html.DisplayFor(model => model[i].emp_salary)</td>
<td>#Html.DisplayFor(model => model[i].emp_joining_date)</td>
<td>#Html.ActionLink("PDF", "UploadPdf", new { id = Model[i].emp_id }) </td>
<td>#(Html.DisplayFor(model => model[i].emp_status).ToString() == "1" ? "Active" : "Inactive")</td>
<td>#Html.TextBoxFor(model => model[i].emp_order, new { style = "width: 35px" })</td>
<td>#Html.HiddenFor(model => model[i].emp_id)</td>
</tr>
}
</tbody>
</table>
<button type="submit" value="Order" onclick="location.href='#Url.Action("UpdateOrder","Employee")'">Order</button>
}
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index", new { page }))`
---This is my controller action method---
[HttpPost]
public ActionResult UpdateOrder(PagedList<Employee> obj_view)
{
foreach (var abc in obj_view)
{
Employee obj = new Employee();
obj.emp_order = abc.emp_order;
obj.emp_id = abc.emp_id;
obj.Mode = "O";
Employee.InsertUpdateEmployee(obj);
}
return RedirectToAction("Index");
}
I looked deeply into your code , as per my point of view, below line may cause the error.
**<button type="submit" value="Order" onclick="location.href='#Url.Action("UpdateOrder","Employee")'">Order</button>
}**
Reason:
When you post the data through the form post, you no need to specify the onclick in the submit button
Solution:
Just replace the above line with simple submit button like this
**<input type="submit" value="Order" class="btn btn-default" />**
And see in the button click event whether you get the data or not using breakpoint.
Hope you will surely get the data now , kindly let me know your thoughts or feedbacks
Thanks
Karthik

query data not show in mvc 4 View

I have created View model for combining two several classes to display several models in a single view. I have created linq query to display data in View. this is my Controller.
public ActionResult Details(int id = 0)
{
var sp_details = (from s in db.service_provider
join p in db.pictures on s.SPID equals p.SPID
join c in db.cities on s.City_ID equals c.City_ID
//where s.SPID==id
select new ImageData()
{
SPID = s.SPID,
Sp_name = s.Sp_name,
Sp_location = s.Sp_location,
Sp_description = s.Sp_description,
Sp_rate = s.Sp_rate,
service_type = s.service_type,
Cityname= c.Cityname,
pic = p.pic });
if (sp_details == null)
{
return HttpNotFound();
}
return View(sp_details);
}
This is Details View. I want to get one specific Profile to View.
#model IEnumerable<WEB1.ViewModel.ImageData>
#{
ViewBag.Title = "Details";
}
<div class="span9">
#foreach (var item in Model)
{
<p class="name">#Html.DisplayFor(modelItem => item.Sp_name)</p>
<p class="cattype">#Html.DisplayFor(modelItem => item.Sp_location)</p>
<table>
<tr>
<td>Opening Hours</td>
<td> #Html.DisplayFor(modelItem => item.Cnt_wh)</td>
</tr>
<tr>
<td></td>
<td>#Html.DisplayFor(modelItem => item.Sp_description)</td>
</tr>
<tr>
<td>Rate</td>
<td>#Html.DisplayFor(modelItem => item.Sp_rate)</td>
</tr>
<tr>
<td></td>
<td><p>#Html.ActionLink("Back to List", "Hotel")</p></td>
</tr>
</table>}
this is Index View. it passed id value after click on hyperlink.
#foreach (var item in Model)
{
<div class="item1">
<img src="data:image/png;base64,#Convert.ToBase64String(item.pic,0,item.pic.Length)" width="100" />
<p class="name">#Html.ActionLink(item.Sp_name, "Details", new { id = item.SPID },null)</p>
<p class="cattype">#Html.DisplayFor(modelItem => item.Sp_location)</p>
<p>#Html.DisplayFor(modelItem => item.Cityname)</p>
<p>#Html.DisplayFor(modelItem => item.Sp_rate)</p>
</div>
}
I have removed commented line in query then I got all list items. But I want to get one specific value.I have added commented line and then I got Blank page with out error but no data.

Wrap column Table to new row on small screens using bootstrap

I have a table on one of my pages using bootstrap for my responsive design. When on a small screen I want to move one of the columns below the other two. Is this possible?
as you can see there are 5 columns below when on desktop. While on small screens I want the note column to go below the other columns.
#foreach (var item in Model.TicketNotes.OrderBy(m => m.TicketNoteDate).Reverse())
{
<tr>
<td style="text-align: center">
#Html.DisplayFor(modelItem => item.TicketNoteDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserNote.FullName)
</td>
<td style="text-align: center" class="hidden-xs">
#if (item.PublicFlag == true)
{
<span>Public</span>
}
else
{
<span>Private</span>
}
</td>
<td>
#Html.DisplayFor(modelItem => item.Note)
</td>
<td>
<div>
#if (item.AttachmentName != null)
{
string path = System.Configuration.ConfigurationManager.AppSettings["MediaFolder"] + "/Tickets/" + ViewBag.ticketNumber + "/" + item.AttachmentName;
if (System.IO.File.Exists(path))
{
#Html.ActionLink(item.AttachmentName, "ViewAttachment", new { controller = "File", filePath = path, fileName = item.AttachmentName }, new { target = "_blank" });
}
}
</div>
</td>
#*<td>
#Html.ActionLink("Edit", "EditTicketNote", "TicketNote", null,
new { id = item.TicketNoteId, ticketNumber = Model.TicketNumber, returnUrl = Model.ReturnUrl, SearchCategory = Model.SearchCategory, SearchStatus = Model.SearchStatus,
SearchTechnician = Model.SearchTechnician, SearchUser = Model.SearchUser, page = ViewBag.page })
</td>*#
</tr>

Resources