MVC5 foreach loop change class based on SQL field - asp.net-mvc

I'am learning MVC5 & Entity Framework 6, and have accomplished a connection to a SQL Database.
I need to change the class of the <tr> field based on the TicketStatus.StatusID result
For Example If the StatusID =1 then use:
<tr class="ticket even status-new priority-low">
if the statusID = 2 then use:
<tr class="ticket even status-open priority-low">
Etc.. Etc..
This is the current Foreach loop code I have based on the number fields to display in a Bootstrap table.
#foreach (var item in Model)
{
<tr class="ticket even status-new priority-low">
<td class="status"><span>#Html.DisplayFor(modelItem => item.TicketStatus.Status)</span></td>
<td class="number"><ul class="user-dashboard-tickets"><li class="user-dashboard-tickets"><span>#Html.DisplayFor(modelItem => item.TicketID)</span></li></ul></td>
<td class="assigned">#Html.DisplayFor(modelItem => item.TicketOwner.OwnerName)</td>
<td class="title"><h2>#Html.DisplayFor(modelItem => item.Title)</h2></td>
<td class="type">Problem</td>
<td class="assigned">test.user</td>
<td class="age">2 days</td>
</tr>
}
I don't know if you can put another foreach loop inside the loop? or add a query to the <tr> field?

you can put any code inside Razor view, even inside a loop, like this:
var statusClass = "";
switch (TicketStatus.StatusID){
case 1:
statusClass = "status-open";
break;
}
<tr class="ticket even #statusClass priority-low">

Related

Show two tables in the view using data from the same model, with one containing duplicates while the other has distinct rows

I have two tables in a single view, with the first one showing the results of a query using this controller:
Controller:
public ActionResult ResultDetails(int? id)
{
var tenders = from t in db.Tenders.Include(t => t.Compendium).Include(t => t.TrainerRegistration) select t;
tenders = tenders.Where(q => q.Compendium.InstitutionID==id);
return View(tenders.ToList());
}
Displaying the data in the first table is pretty straightforward. However, when I tried using the same scaffolded razor syntax in my second table, this returned duplicate rows particularly in my item2.TrainerRegistration.NTTC column
#foreach (var item2 in Model)
{
<tr>
<td nowrap>
#Html.DisplayFor(modelItem => item2.TrainerRegistration.Trainer.TrainerName)
</td>
<td nowrap>
#Html.DisplayFor(modelItem => item2.TrainerRegistration.Qualification.Title)
</td>
<td nowrap>
#Html.DisplayFor(modelItem => item2.TrainerRegistration.NTTC)
</td>
</tr>
}
the query in the controller would really return duplicates, but how can I remove these duplicate rows in the second table? I have tried adding GroupBy() or Distinct() to my NTTC property but I can't get it to work this way or its other variations:
#foreach (var item2 in Model.GroupBy(x => x.TrainerRegistration.NTTC).ToList())
After multiple guesses, altering the argument inside #foreach would always affect the #Html.DisplayFor(modelItem => item2.****) in one way or another. I'm done guessing at this point and would really appreciate it if someone could point me to the correct way of doing this.
I was able to resolve my problem by using First(), on rows where TrainerRegistrationID is being repeated
#foreach (var item2 in Model.GroupBy(x => x.TrainerRegistrationID).Select(y => y.First()))

Add count/sub-count to mvc view

I've got a view that is showing the breakdown of all fault categories reported and the area that they've been reported in. What I need to get is a total count of the number of faults of each category, and then a sub count of each area under that type. I've seen around that there are options to use Model.Count(), however whenever I try that it doesn't return the right number.
The view code that I'm using is below:
<table class="table table-responsive">
<tr>
#foreach (var catGroup in Model.GroupBy(item => item.job_category))
{
foreach (var itemCat in catGroup.Take(1))
{
if (itemCat.job_category != null)
{
<td>
<table id="Tbl_Total_#itemCat.job_category">
<tr>
<th>
#Html.DisplayFor(modelItem => itemCat.job_category)
</th>
</tr>
#foreach (var item in catGroup.GroupBy(item => item.job_area))
{
foreach (var itemArea in item.Take(1))
{
<tr>
<td>
#Html.DisplayFor(modelItem => itemArea.job_area)
</td>
</tr>
}
}
</table>
</td>
}
}
}
</tr>
</table>
Can someone point me in the right direction to get a count per category, and per area under the categories?
Thanks
You can get the number of element per group calling Count extension method. eg, for the category groups you can do this:
catGroup.Count()
And you can do the same for the areas:
item.Count()

Slow view building

I am in the process of converting an old asp.net forms application to MVC. I have run into a snag where I am displaying results of a search.
I have an entity framework model of Classes, Class Details, Rosters and Class instructors.
I have a search page where I wish to display all of the class details by class selected.
View:
#using System.Diagnostics
#model IEnumerable<SafetyReports.Models.DataModel.ClassDetails>
<div>
<table>
<tr>
<th>
Class Date
</th>
<th>
Location
</th>
<th>
Region
</th>
<th>
# of Attendees
</th>
</tr>
#foreach (var c in Model)
{
Debug.WriteLine(c.ClassDetailID);
<tr>
<td>
#c.ClassDate
</td>
<td>
#c.Location
</td>
<td>
#c.Region
</td>
<td>
#c.ClassRosters.Count
</td>
<td>
<input type="button" value="Detail" onclick="alert(#c.ClassDetailID)"/>
</td>
</tr>
}
</table>
</div>
controller:
public PartialViewResult SelectCourse(string id)
{
var e = new Entities();
var i = e.ClassDetails.Where(x => x.ClassID.ToString() == id).ToList();
return PartialView("_ClassesDetail", i);
}
My problem is that it seem to take about 1 second per 2-3 classes. I have one class type that has 1300 records and it takes about 5-6 minutes to return the view. What am I doing wrong? In the asp.net forms application I have a gridview that returns the same amount of data in seconds if that long. It isnt using EF though, just a sqldatasource. Could this be lazy loading?
firstly, as seen before using a int instead of a string for 'id' will speed up your EF query.
Here's one way to speed up the view rendering (or at least make it cleaner):
In view replace all the #foreach loop by a simple :
//here Razor will automatically repeat you model displayTemplate for
//each element of your IEnumerable
#Html.DisplayForModel()
And then define a Display Template for your model
~/Views/Shared/DisplayTemplates/ClassDetails.cshtml
#model SafetyReports.Models.DataModel.ClassDetails
<tr>
<td>
#Model.ClassDate
</td>
<td>
#Model.Location
</td>
<td>
#Model.Region
</td>
<td>
#Model.ClassRosters.Count
</td>
<td>
<input type="button" value="Detail" onclick="alert(#Model.ClassDetailID)"/>
</td>
</tr>
I found my issue, I had related objects being lazy loaded, I fixed the issue with including those objects with:
var i = e.ClassDetails.Where(x => x.ClassID == id).Include(x=>x.ClassInstructors).Include(x=>x.ClassRosters).ToList();

Make an image in a table cell into a link

I have created an e-commerce website and am using a label to display the products from my sql database, the image it shows of these products are not hyperlinks, but this is what I need them to be, I think I have written the right code but I have a "parentControl" error, could someone help plz?
Below is also a link to show you visually what is being asked. REMEMBER the picture is just an image, but needs to be a hyperlink!
private void FillPage()
{
ArrayList teesList = new ArrayList();
if (!IsPostBack)
{
teesList = ConnectionClass.GetTeesBySize("%");
}
else
{
teesList = ConnectionClass.GetTeesBySize(DropDownList1.SelectedValue);
}
StringBuilder sb = new StringBuilder();
HyperLink link = new HyperLink();
link.NavigateUrl = "http://google.com";
parentControl.Controls.Add(link);
foreach (Tees tees in teesList)
{
sb.Append(string.Format(#"<table class='TeesTable'>
<tr>
<th rowspan='1' width='150px'><img runat='server' src='{6}' /</th>
<th width='50px'>Name: </th>
<td>{0}</td>
</tr>
<tr>
<th>Size:</th>
<td>{1}</td>
</tr>
<tr>
<th>Price:</th>
<td>{2}</td>
</tr>
</table>",
tees.name, tees.size, tees.price, tees.id, tees.id, tees.id, tees.image));
LblOutput.Text = sb.ToString();
(https://dl-web.dropbox.com/get/CompetitiveStreakTemplate/Pic.png?_subject_uid=9403629&w=AAD63dzqPQcNMNSU0OwbVBrGjNGFvtt7VWJ6DKwlu4UoPw).
You need to close your <img> tag properly and wrap it in a <a> to make it a hyperlink. Also use <td> instead of <th> for data rows and not headers.
Something a bit more like:
<td rowspan='1' width='150px'>
<a href='{0}.aspx'>
<img runat='server' src='{6}' />
</a>
</td>
You should probably also tidy up the rest of the code appended to your table, checking what is a header or data, and using a <tbody> tag inside the <table>
Edit: looking closer it seems as though you aren't creating the table properly in the first place, change this chunk of your code to do the loop properly:
parentControl.Controls.Add(link);
sb.Append("<table class='TeesTable'><tbody>");
foreach (Tees tees in teesList)
{
sb.Append(string.Format(#"
<tr>
<td rowspan='1' width='150px'>
<a href='{0}.aspx'>
<img runat='server' src='{6}' />
</a>
</td>
<td width='50px'>Name: </td>
<td>{0}</td>
</tr>
<tr>
<td>Size:</td>
<td colspan='2'>{1}</td>
</tr>
<tr>
<td>Price:</td>
<td colspan='2'>{2}</td>
</tr>",
tees.name, tees.size, tees.price, tees.id, tees.id, tees.id, tees.image));
}
sb.Append("</tbody></table>");
LblOutput.Text = sb.ToString();

Insert "where" rule in a "foreach" search

I need some help in order to put a where rule into the foreach search. My goal is to exclude orders where the customerOrder.ERPOrderNumber starts with letter E
The code that i have returns all the orders for the specific customer.
Thank you in advance for your help.
#foreach (var customerOrder in Model.CustomerOrders)
{
<tr>
<td class="mavo-order-date">#customerOrder.OrderDate.ToShortDateString()
</td>
<td class="mavo-status">#customerOrder.Status
</td>
<td class="mavo-order-number">
#customerOrder.OrderNumber
</td>
#if (Model.ShowErpOrderNumber)
{
<td class="mavo-erp-order">#customerOrder.ERPOrderNumber
</td>
}
<td class="mavo-po">#customerOrder.CustomerPO
</td>
<td class="mavo-order-total">#customerOrder.OrderGrandTotal.ToCurrency()
</td>
<td class="mavo-view">
<a class="btn btnStyleA tbm5" href="#Url.Action("OrderHistoryDetail", "Account", new { orderId = customerOrder.ERPOrderNumber })">View Details</a>
</td>
</tr>
}
You can put an if statement inside the foreach loop to only write out the table row when the order number doesn't start with the letter E.
#foreach (var customerOrder in Model.CustomerOrders)
{
#if(!customerOrder.ERPOrderNumber.StartsWith("E"))
{
// Markup goes in here
}
}
Or you can use LINQ to filter the CustomerOrders collection.
#foreach(var customerOrder in Model.CustomerOrders.Where(x => !x.StartsWith("E"))

Resources