Counting how many entries in a different model have a certain criteria - c#

This is a problem I have been working on for a very long time to no avail.
Basically I have two Models: Units and Trades, what i want is when I am on the View for Units, which returns a paged list of the units. What I want is an additional column to the table which returns a count of how many entries in Trades have Trade.Name = model.Name for each Unit.
The first problem I am having is accessing two models from one view. I have tried tons of things based on searching, but can't seem to be able to make anything work.
The second problem is how to actually do the count. Is it possible to use Linq directly from the View? It hasn't been working for me so far.
Thanks in advance or any help!
The important part of the Units view:
#model PagedList.IPagedList<FTv2.Models.Unit>
<table style="border-width: 1px; border-color:#000000; border-style: solid; border-top: 2px; border-top-color:#000000; border-top-style: solid;">
<tr>
<th></th>
<th>Name</th>
<th>Type</th>
<th>Skill</th>
<th>Rating</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#{ ViewBag.ImgUrl = item.Name + ".png";}
<a href="/Images/#ViewBag.ImgUrl" data-lightzap="" ><img src="/Images/#ViewBag.ImgUrl" HEIGHT="66" WIDTH="50" ></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.Skill)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rating)
</td>
<td>
<!-- this is where I would want the count to go. -->
</td>
</tr>
}
</table>
Last issue, not showing any results in the View.
Here's the relevant parts of the controller:
var units = db.Units;
var students = db.Units.Select(u => new UnitViewModel()
{
Unit = u,
TradeCount =
db.Movies.Where(t => t.Name == u.Name).Count()
});
return View(students.ToPagedList(pageNumber, pageSize));

Get everything you need server side and pass it to the view. You can do the count in the controller GET action first, and pass it using ViewBag or add a property in your view model to hold the counts.
[HttpGet]
public ActionResult MyView()
{
var units = _context.Units.Where(//whatever);
var viewModels = units.Select(u => new UnitViewModel()
{
Unit=u,
TradeCount =
context.Trades.Where(t => t.name == u.name).Count()
});
return View(viewModels);
}
EDIT:
I would write a view model class for your view. So instead of the view using a model of List<Unit>, now it uses List<UnitViewModel>.
public class UnitViewModel
{
public Unit Unit {get;set;}
public int TradeCount {get;set;}
}
EDIT VIEW:
#model PagedList.IPagedList<FTv2.Models.UnitViewModel>
<table style="border-width: 1px; border-color:#000000; border-style: solid; border-top: 2px; border-top-color:#000000; border-top-style: solid;">
<tr>
<th></th>
<th>Name</th>
<th>Type</th>
<th>Skill</th>
<th>Rating</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#{ ViewBag.ImgUrl = item.Name + ".png";}
<a href="/Images/#ViewBag.ImgUrl" data-lightzap="" ><img src="/Images/#ViewBag.ImgUrl" HEIGHT="66" WIDTH="50" ></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Skill)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit.Rating)
</td>
<td>
#Html.DisplayFor(modelItem => item.TradeCount)
</td>
</tr>
}
</table>

Related

Null reference in Model

I am having this problem when i press a link to view data in pdf:
System.NullReferenceException: 'Object reference not set as an instance of an object.'
This problem arises when I try to display the SQL values ​​in PDF.
As you can see in the image, there is a link to see the values ​​in PDF, when you click there the error already mentioned will appear.
I share the code:
Controller:
public ActionResult Index(string buscarTitulo)
{
PDFPrinter db = new PDFPrinter();
ViewBag.CurrentFilter = buscarTitulo;
var datos = from s in db.SQLs
select s;
if (!String.IsNullOrEmpty(buscarTitulo))
{
datos = datos.Where(s => s.Titulo.ToString().Contains(buscarTitulo.ToUpper()));
}
return View(datos.ToList());
}
public ActionResult Pdf()
{
var reporte = new ActionAsPdf("Index");
return reporte;
}
public ActionResult Impresion(double? tit) {
using (PDFPrinter db = new PDFPrinter()) {
V_CuetaWeb v = db.SQLs.FirstOrDefault(c => c.Titulo == tit);
List<V_CuetaWeb> lista = new List<V_CuetaWeb>();
lista.Add(v);
var reporte = new PartialViewAsPdf("Pdf", v);
return reporte;
}
}
Index:
#model IEnumerable<ProvidusCuotas.V_CuetaWeb>
#{
ViewBag.Title = "Inicio";
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Inicio</title>
</head>
<body>
<form id="form">
<div>
#using (Html.BeginForm())
{
<p>
Título: #Html.TextBox("buscar", ViewBag.CurrentFilter as string)
<input type="submit" value="Filtrar" /><br />
<input type="button" value="Imprimir" onclick="window.print()" />
</p>
}
</div>
<div>
<table border="1">
#foreach (var item in Model)
{
<tr>
<th scope="row" abbr="Suscriptor">Suscriptor: </th>
<td>
<b>#Html.DisplayFor(modelItem => item.Apellido), #Html.DisplayFor(modelItem => item.Nombre)</b>
</td>
<td>Título: #Html.DisplayFor(modelItem => item.Titulo)</td>
</tr>
PDF:
#model IEnumerable<ProvidusCuotas.V_CuetaWeb>
#{
ViewBag.Title = "PDF";
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Inicio</title>
</head>
<body>
<form id="form">
<div>
<table border="1">
#foreach (var item in Model)
{
<tr>
<th scope="row" abbr="Domicilio">Domicilio: </th>
<td>
#Html.DisplayFor(modelItem => item.Domicilio)
</td>
<td></td>
<td></td>
<td></td>
<td>Valor Nominal: #Html.DisplayFor(modelItem => item.ValNom)</td>
</tr>
<tr>
<th scope="row" abbr="Barrio">Barrio: </th>
<td>
#Html.DisplayFor(modelItem => item.Barrio)
</td>
</tr>
<tr>
<th scope="row" abbr="Localidad">Localidad: </th>
<td>
#Html.DisplayFor(modelItem => item.Localidad)
</td>
</tr>
<tr>
<th scope="row" abbr="Telefono">Teléfono: </th>
<td>
#Html.DisplayFor(modelItem => item.Telefono)
</td>
</tr>
<tr>
<th scope="row" abbr="Celular">Celular: </th>
<td>
#Html.DisplayFor(modelItem => item.Celular)
</td>
</tr>
<tr>
<th scope="row" abbr="Descripcion">D. Plan Actual: </th>
<td>
#Html.DisplayFor(modelItem => item.DescPlanActual)
</td>
</tr>
<tr>
<th scope="row" abbr="Fecha">Fecha Sorteo: </th>
<td>
#Html.DisplayFor(modelItem => item.FechaSorteo)
</td>
</tr>
<tr>
<th>Zona: #Html.DisplayFor(modelItem => item.acidzona)</th>
<th>Cobrador: #Html.DisplayFor(modelItem => item.Cobrador)</th>
<th>Código: #Html.DisplayFor(modelItem => item.Codigo)</th>
<th>Título: #Html.DisplayFor(modelItem => item.Titulo)/#Html.DisplayFor(modelItem => item.Endoso)</th>
<th>Sorteo: #Html.DisplayFor(modelItem => item.Sorteo)</th>
<th>Cuota: #Html.DisplayFor(modelItem => item.Cuota)</th>
<th>Vencimiento: #Html.DisplayFor(modelItem => item.Vencimiento)</th>
<th>Monto: #Html.DisplayFor(modelItem => item.Monto)</th>
</tr>
}
</table>
</div>
</form>
</body>
</html>
PDFPrinter class:
public partial class PDFPrinter : DbContext
{
public PDFPrinter()
: base("name=VisorPDF")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
//public virtual DbSet<V_CuetaWeb> V_CuetaWeb { get; set; }
public virtual DbSet<V_CuetaWeb> SQLs { get; set; }
}
Any sugerence? how to solve this?
I don't understan the mistake
I think your flow needs to change, so index will pass list of pdf objects. and it iterate from view and display a table. This part correct.
Then you click from one link, then it should pass that click object to second view. Then it will display you object values.
So pdf view model should be
#model ProvidusCuotas.V_CuetaWeb
Then no need to have foreach loop. Just access the properties and display those.
and you c# method should be like this
public ActionResult Impresion(double? tit) {
using (PDFPrinter db = new PDFPrinter())
{
V_CuetaWeb v = db.SQLs.FirstOrDefault(c => c.Titulo == tit);
return View("Pdf", v);
}
}

Transfer data to other page in asp.net mvc

I have 3 models dailyTransaction , Contract , and ContractMonth .
I want transfer some of data from daily Transaction and Contract to the Contract Month page or table But i do not what is the wrong the table is empty and there no any data .
This is my Contract Month Controller:
public ActionResult Index(int id)
{
var contractMonth = _context.ContractMonth.Where(c => c.ContractsId == id).Include(s => s.contracts).Include(d => d.dailyTransactions).ToList();
return View(contractMonth);
}
This is the view :
<table class="table table-bordered f" cellspacing="0" id="employeetable">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.ContractsId)</th>
<th>#Html.DisplayNameFor(model => model.Monthe)</th>
<th>#Html.DisplayNameFor(model => model.Amount)</th>
<th>#Html.DisplayNameFor(model => model.Receipt)</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.contracts.Contract_Num)
</td>
<td>
#Html.DisplayFor(modelItem => item.dailyTransactions.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.contracts.AmountOfRent)
</td>
</tr>
}
</tbody>
</table>
enter image description here
enter image description here

Filter data in other page in ASP.NET MVC

I have one table which is for contracts , And I have link beside each contract , when I click to the link they transfer to other page which is contract month but i want to display the data only for that contract which I click not all data.
Contact View :
#using (Html.BeginForm())
{
#Html.ActionLink("Create", "Create")
<table class="table table-bordered f" cellspacing="0">
<thead>
<tr>
</tr>
</thead>
#foreach (var item in Model)
{
<tbody>
<tr>
<td>
#Html.DisplayFor(modelItem => item.Contract_Num)
</td>
<td>
#Html.DisplayFor(modelItem => item.Contract_Start)
</td>
<td>
#Html.DisplayFor(modelItem => item.Contract_End)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.typeOfRent.TypeOfRent_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.AmountOfRent)
</td>
<td>
#Html.DisplayFor(modelItem => item.Total)
</td>
<td>
#Html.DisplayFor(modelItem => item.customers.Customer_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.sections.Section_Name)
</td>
<td>
#Html.ActionLink("Contract Month", "Index", "ContractMonth")
</td>
</tbody>
}
</table>
contract month view :
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.contracts.Contract_Num)
</td>
<td>
#Html.DisplayFor(modelItem => item.Monthe)
</td>
<td>
#Html.DisplayFor(modelItem => item.contracts.AmountOfRent)
</td>
<td>
#Html.DisplayFor(modelItem => item.Receipt)
</td>
<td>
#{
var Balance = item.contracts.AmountOfRent - item.Receipt;
}
#Balance
</td>
Contract month controller:
public ActionResult Index()
{
var ContractMonth =_context.ContractMonth.Include(s => s.contracts).ToList();
return View(ContractMonth);
}
First of all change your Index action method inside ContractMonthController to get specific records with respect to ContractId
public ActionResult Index(int id)
{
var contractMonth = _context.ContractMonth.Where(c => c.ContractsId == id).Include(s => s.contracts).ToList();
return View(contractMonth);
}
And then change your action to accept id as query string parameter,
<td>
#Html.ActionLink("Contract Month", "Index", "ContractMonth", new { id = item.Contracts_Id }, null)
</td>
You can add the primary key (e.g. Id) of each contract to the url of each link as a query string. Then when getting the contract month data you can use the pk parameter to filter the data, for example (in the contract month controller):
public ActionResult Index(int contractId)
{
var ContractMonth =_context.ContractMonth.Where(c => c.ContractId == contractId).Include(s => s.contracts).ToList();
return View(ContractMonth);
}

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.

ASP MVC passing model data in view back as form data

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>
}

Categories

Resources