Show subset of data in MVC3 view page - c#

I'm returning quite a few rows on a view page. I'm wanting to show several tables, each being a subset of the full results. I have a foreach loop, and I'm wondering how I filter the results so "ResponseCode > 400" and "ExtFlag = 1"
#foreach (var res in Model.LinkCheckerResults)<br>
{
<tr>
<td>
#Html.DisplayFor(model => res.SourceURL)<br>
</td>
<td>
#Html.DisplayFor(model => res.TargetURL)
</td>
<td>
#Html.DisplayFor(model => res.Response)
</td>
</tr>
}
Many Thanks.

Assuming ResponseCode and ExtFlag are members of whatever LinkCheckerResults returns, you can do this as you normally would in a foreach loop in C#.
With LINQ:
#foreach (var res in Model.LinkCheckerResults
.Where(lcr => lcr.ResponseCode > 400 && lcr.ExtFlag == 1))
{
<tr>
<td>
#Html.DisplayFor(model => res.SourceURL)<br>
</td>
<td>
#Html.DisplayFor(model => res.TargetURL)
</td>
<td>
#Html.DisplayFor(model => res.Response)
</td>
</tr>
}
Or an if statement:
#foreach (var res in Model.LinkCheckerResults)<br>
{
if (res.ResponseCode > 400 && res.ExtFlag == 1)
{
<tr>
<td>
#Html.DisplayFor(model => res.SourceURL)<br>
</td>
<td>
#Html.DisplayFor(model => res.TargetURL)
</td>
<td>
#Html.DisplayFor(model => res.Response)
</td>
</tr>
}
}
Or (the true MVC way) provide the collection pre-filtered as a ViewData/ViewBag property.

you can either filter your model before is returned to the view or do :
#foreach (var res in Model.LinkCheckerResults.Where(x=>x.Response > 400 && x.ExtFlag = 1).ToList())<br>
{
<tr>
<td>
#Html.DisplayFor(model => res.SourceURL)<br>
</td>
<td>
#Html.DisplayFor(model => res.TargetURL)
</td>
<td>
#Html.DisplayFor(model => res.Response)
</td>
</tr>
}

Related

How to display the difference between 2 columns in a table

I am having an Audit Table that displays 2 columns OLD Data, New data which are in XML while displaying the table, I want only the differences between the 2 columns to be listed.
I have converted the data to XML to present my old and new data and I have removed the XML initialization for easy readability.
Controller
public async Task < IActionResult > History(string RefNum) {
if (RefNum == null) {
return RedirectToAction("Index");
}
var obj = await (from x in _db.AuditModel select x).Where(x => x.RefNum.Equals(RefNum)).ToListAsync();
if (obj == null) {
return RedirectToAction("Index");
}
return PartialView(obj);
}
View Page
#model IEnumerable<Flight_info.Models.AuditModel>
<div>
<div class="modal-header">
<h2 class="modal-title">
HISTORY
</h2>
<button class="close" data-dismiss="modal" align="right">×</button>
</div>
<div class="modal-body">
<table class="table" style="table-layout: fixed; word-wrap: break-word">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.RefNum)
</th>
<th>
#Html.DisplayNameFor(model => model.ChangeMade)
</th>
<th>
#Html.DisplayNameFor(model => model.OldData)
</th>
<th>
#Html.DisplayNameFor(model => model.NewData)
</th>
<th>
#Html.DisplayNameFor(model => model.ModifiedOn)
</th>
<th>
#Html.DisplayNameFor(model => model.ModifiedBY)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.RefNum)
</td>
<td>
#Html.DisplayFor(modelItem => item.ChangeMade)
</td>
<td>
#Html.DisplayFor(modelItem => item.OldData)
</td>
<td>
#Html.DisplayFor(modelItem => item.NewData)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModifiedOn)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModifiedBY)
</td>
</tr>
}
</tbody>
</table>
<div>
<a asp-action="Index">Back to List </a>
</div>
</div>
</div>
[This is currently my output][1]
[1]: https://i.stack.imgur.com/KeNHk.png
But I want only the differences to be displayed. Please Help.
1- If you want to list only the rows that OldData != NewData, then use filter in Where clause. such as below:
var obj = await (from x in _db.AuditModel select x)
.Where(x => x.RefNum.Equals(RefNum) && x.OldData != x.NewData).ToListAsync();
2-If you want to show all rows and display difference value of OldData and NewData then write below code in your view
<td>
#Html.DisplayFor(modelItem => item.OldData - item.NewData)
</td>
i found the solution myself.Instead of using XML i converted my objects to json and i used JSON DIFF.
While displaying i used jquery to dynamically create a table to display the key and value pairs

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

C# MVC filtering a table via a dropdown

I have a view which has a table that displays values. I would like to add a drop down that filters the results of the status column. So for example if I select "Reviewing", only records with the "Reviewing" status will appear. Below I have my view.
#model IEnumerable<DRT.Models.Master>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.RequestType.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Reviewer.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Status.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.ProjectName)
</th>
<th>
#Html.DisplayNameFor(model => model.ProjectLocation)
</th>
<th>
#Html.DisplayNameFor(model => model.Requestor)
</th>
<th>
#Html.DisplayNameFor(model => model.DateReceived)
</th>
<th>
#Html.DisplayNameFor(model => model.ReviewCompDate)
</th>
<th>
#Html.DisplayNameFor(model => model.ProjectFolerLink)
</th>
<th>
#Html.DisplayNameFor(model => model.ModellingReferralDate)
</th>
<th>
#Html.DisplayNameFor(model => model.ModellingReviewCompletionDate)
</th>
<th>
#Html.DisplayNameFor(model => model.SewerMaintenanceReferralDate)
</th>
<th>
#Html.DisplayNameFor(model => model.SewerMaintenanceReviewCompletionDate)
</th>
<th>
#Html.DisplayNameFor(model => model.FlowControlReferralDate)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.RequestType.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Reviewer.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProjectName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProjectLocation)
</td>
<td>
#Html.DisplayFor(modelItem => item.Requestor)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateReceived)
</td>
<td>
#Html.DisplayFor(modelItem => item.ReviewCompDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProjectFolerLink)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProjectComments)
</td>
<td>
#Html.DisplayFor(modelItem => item.DischargeLocationID)
</td>
<td>
#Html.DisplayFor(modelItem => item.DischargeDistrict)
</td>
<td>
#Html.DisplayFor(modelItem => item.SystemType)
</td>
<td>
#Html.DisplayFor(modelItem => item.AffectedRequlator)
</td>
<td>
#Html.DisplayFor(modelItem => item.StartDateOfDischarge)
</td>
<td>
#Html.DisplayFor(modelItem => item.DurationOfDischarge)
</td>
<td>
#Html.DisplayFor(modelItem => item.RequestFlowRate)
</td>
<td>
#Html.DisplayFor(modelItem => item.ApprovedDischargeRate)
</td>
<td>
#Html.DisplayFor(modelItem => item.DischargeLocationComments)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModellingReferralDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModellingReviewCompletionDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.SewerMaintenanceReferralDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.SewerMaintenanceReviewCompletionDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.FlowControlReferralDate)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.MasterId }) |
#Html.ActionLink("Details", "Details", new { id=item.MasterId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.MasterId })
</td>
</tr>
}
</table>
You basically need a SELECT element in your view and when use selects something, you may post the selected value to the action method where you will use this value when getting data from your db.
You may create a new view model
public class ListAndSearchVm
{
public IEnumerable<DRT.Models.Master> Data { set;get;}
public IEnumerable<SelectListItem> Statuses { set;get;}
public string SelectedStatus { set;get;}
}
Now in your GET action, you need to load the Statuses property of the view model and the Data property. Have a parameter to accept the selected option value from your status filter dropdown. Based on the value of this parameter get the filtered data.
public ActionResult Index(string selectedStatus="")
{
var vm= new ListAndSearchVm();
//Hard coding 2 items for demo. You can read this from your db table
vm.Statuses = new List<SelectListItem> {
new SelectListITem { Value="Open", Text="Open"},
new SelectListITem { Value="Closed", Text="Closed"},
};
var data= dbContext.Masters;
if(!String.IsNullOrEmpty(selectedStatus))
{
data = data.Where(f=>f.Status.Name==selectedSatatus);
}
vm.Data = data.ToList();
return View(vm);
}
Now in your view
#model ListAndSerchVm
#using(Html.BeginForm("Index","YourControllerName",FormMethod.Get))
{
<label> Select a status</label>
#Html.DropDownListFor(f=>f.SelectedStatus,Model.Statuses,"Select")
<input type="submit" value="Filter" />
}
<table>
<tr>
<th>Request type</th>
<th>Reviewer</th>
<th>Status</th>
</tr>
#foreach(var item in Model.Data)
{
<tr>
<td>#item.RequestType.Name)</td>
<td>#item.Reviewer.Name</td>
<td>#item.Status.Name</td>
</tr>
}
</table>

Use checkboxes in MVC view and pass checked state back to controller for processing

I have an IList of objects that I pass using a ViewModel to my view.
[HttpGet]
public ActionResult Reminder()
{
using(var db = new SalonContext())
{
var tomorrow = DateTime.Today.AddDays(1);
var homeSalon = GetHomeSalonId();
var myAppointments = db.Appointments.Include(c => c.Customer).Include(c => c.Treatment).Include(c => c.Stylist).Include(c => c.Salon).Where(c => c.SalonId == homeSalon).ToList();
var tomorrowsAppointments = myAppointments.Where(a => a.Start.Date == tomorrow).Select(rem => new FutureAppointment
{
AppointmentId = rem.AppointmentId,
Name = rem.Customer.Title + " " +rem.Customer.FirstName + " " + rem.Customer.Surname,
AppointmentTime = rem.Start,
Salon = rem.Salon.Name,
Stylist = rem.Stylist.FirstName,
Treatment = rem.Treatment.Name,
Email = rem.Customer.EMail,
SendReminder = true
}).ToList();
return View(tomorrowsAppointments);
}
}
The view renders the list with the check boxes using this code:
#model IList<MySalonOrganiser.Models.FutureAppointment>
#{
ViewBag.Title = "Email Reminders";
}
<h2>#ViewBag.Title</h2>
#using(Html.BeginForm("Reminder", "Appointment", FormMethod.Post))
{
#Html.AntiForgeryToken()
<table class="table">
<tr>
<th>
Send Reminder
</th>
<th>
Name
</th>
<th>
Appointment Time
</th>
<th>
Salon
</th>
<th>
Treatment
</th>
<th>
Stylist
</th>
<th>
EMail
</th>
<th></th>
</tr>
#for (var i =0; i < Model.Count; i++)
{
<tr>
<td>
#Html.CheckBoxFor(x => x[i].SendReminder)
</td>
<td>
#Html.DisplayFor(x => x[i].Name)
</td>
<td>
#Html.DisplayFor(x => x[i].AppointmentTime)
</td>
<td>
#Html.DisplayFor(x => x[i].Salon)
</td>
<td>
#Html.DisplayFor(x => x[i].Treatment)
</td>
<td>
#Html.DisplayFor(x => x[i].Stylist)
</td>
<td>
#Html.DisplayFor(x => x[i].Email)
</td>
</tr>
}
</table>
<div>
<input type="Submit" value="Send Reminders" />
</div>
}
When I post the view back to the controller, I see the list's items of type FutureAppointment in the returned model, but everything except the checkbox state is null.
Can anyone help me with why and how to fix this so I see all the model data?
Jason.
It's because your form only contains input fields for the checkboxes. The DisplayFor helper will only create a text or label or whatever displaying the value of the other fields. You can fix this by adding hidden inputs for them:
#for (var i =0; i < Model.Count; i++)
{
<tr>
<td>
#Html.CheckBoxFor(x => x[i].SendReminder)
</td>
<td>
#Html.DisplayFor(x => x[i].Name)
#Html.HiddenFor(x => x[i].Name)
</td>
<td>
#Html.DisplayFor(x => x[i].AppointmentTime)
#Html.HiddenFor(x => x[i].AppointmentTime)
</td>
<td>
#Html.DisplayFor(x => x[i].Salon)
#Html.HiddenFor(x => x[i].Salon)
</td>
<td>
#Html.DisplayFor(x => x[i].Treatment)
#Html.HiddenFor(x => x[i].Treatment)
</td>
<td>
#Html.DisplayFor(x => x[i].Stylist)
#Html.HiddenFor(x => x[i].Stylist)
</td>
<td>
#Html.DisplayFor(x => x[i].Email)
#Html.HiddenFor(x => x[i].Email)
</td>
</tr>
}
You are not posting back the values. Html.DisplayFor does not generate input tags, and only inputs inside a form are posted back to server. You will have to use Html.TexBoxFor or Html.HiddenFor methods for those properties.
Under each of the DisplayFor calls, add a #Html.HiddenFor(x=>x[i].Property) call to add a hidden field containing the same value.
The hidden field values will then get posted by the form and bound to your model when the data hits your controller.
The DisplayFor will only add a label to the output (unless overridden for the model with a display template), label values do not get posted by a form.

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.

Categories

Resources