How to display a list and fields using Razor - asp.net-mvc

pretty new to mvc 5.
I have a model that contains a field and a list.
I wish to display both in my view.
this is my model:
public class AdminChargeHistory
{
public List<StripeChargeHistory> Charges = new List<StripeChargeHistory>();
public string ErrorMessage { get; set;] }
}
public class StripeChargeHistory
{
public int TransactionId { get; set; }
public string Amount { get; set; }
public string AmountRefunded { get; set; }
public string CustomerId { get; set; }
public Nullable<bool> Paid { get; set; }
public string Status { get; set; }
public string ChargeId { get; set; }
public string InvoiceId { get; set; }
public string BalanceTransId { get; set; }
public Nullable<bool> Live { get; set; }
public Nullable<int> Month { get; set; }
public Nullable<int> Year { get; set; }
}
my controller:
public ActionResult MissedPayments()
{
var adminChargeHistory = new AdminChargeHistory();
try
{
var stripeRepository = new StripeRepository();
var results = stripeRepository.GetMissedPayments(-1, -1, false);
foreach (var result in results)
{
var stripeChargeHistory = new StripeChargeHistory();
stripeChargeHistory.Amount = result.Amount;
stripeChargeHistory.AmountRefunded = result.AmountRefunded;
stripeChargeHistory.BalanceTransId = result.BalanceTransId;
stripeChargeHistory.ChargeId = result.ChargeId;
stripeChargeHistory.CustomerId = result.CustomerId;
stripeChargeHistory.InvoiceId = result.InvoiceId;
stripeChargeHistory.Live = result.Live;
stripeChargeHistory.Month = result.Month;
stripeChargeHistory.Paid = result.Paid;
stripeChargeHistory.Status = result.Status;
stripeChargeHistory.TransactionId = result.TransactionId;
stripeChargeHistory.Year = result.Year;
adminChargeHistory.Charges.Add(stripeChargeHistory);
}
}
catch (Exception ex)
{
adminChargeHistory.ErrorMessage = ex.Message;
}
return View(adminChargeHistory);
}
my view:
#model InformedProducts.Models.AdminChargeHistory
#{
ViewBag.Title = "Missed Payments";
}
<h2>Missed Payments</h2>
<table class="grid">
<tr>
<th>Customer Id</th>
<th>Amount</th>
<th>Month</th>
<th>Year</th>
</tr>
#foreach (var item in Model.StripeChargeHistory)
{
<tr>
<td class="left"><#item.CustomerId></td>
<td class="left"><#item.Amount></td>
<td class="left"><#item.Month></td>
<td class="left"><#item.Year></td>
</tr>
#}
#Html.LabelFor(m=>m.ErrorMessage)
</table>
but errors here:
InformedProducts.Models.AdminChargeHistory
and here?
#Html.LabelFor(m=>m.ErrorMessage)
I cannot see what I am doing wrong?

Model - Add getter/setter for Charges and empty constructor.
public class AdminChargeHistory
{
public AdminChargeHistory()
{
Charges = new List<StripeChargeHistory>();
}
public ICollection<StripeChargeHistory> Charges { get; set; }
public string ErrorMessage { get; set; }
}
Controller - take advantage of LINQ
public ActionResult MissedPayments()
{
var adminChargeHistory = new AdminChargeHistory();
try
{
var stripeRepository = new StripeRepository();
var results = stripeRepository.GetMissedPayments(-1, -1, false);
adminChargeHistory.Charges = results.Select(result => new StripeChargeHistory
{
Amount = result.Amount,
CustomerId = result.CustomerId,
Month = result.Month,
Year = result.Year
}).ToList();
}
catch (Exception ex)
{
adminChargeHistory.ErrorMessage = ex.Message;
}
return View(adminChargeHistory);
}
View - Reference the Charges collection property
#model InformedProducts.Models.AdminChargeHistory
#{
ViewBag.Title = "Missed Payments";
}
<h2>Missed Payments</h2>
<table class="grid">
<tr>
<th>Customer Id</th>
<th>Amount</th>
<th>Month</th>
<th>Year</th>
</tr>
#foreach (var item in Model.Charges)
{
<tr>
<td class="left"><#item.CustomerId></td>
<td class="left"><#item.Amount></td>
<td class="left"><#item.Month></td>
<td class="left"><#item.Year></td>
</tr>
#}
#Html.LabelFor(m=>m.ErrorMessage)
</table>
if you have red squiggly under #model InformedProducts.Models.AdminChargeHistory you might have the wrong namespace.. Remove InformedProducts.Models. and put cursor on AdminChargeHistory and hit ctrl + . (period) and it should find the correct namespace.

It should be:
#foreach (var item in Model.Charges)
{
// code removed for brevity...
}
This is because your model AdminChargeHistory has a property named Charges which is enumerable. What you are using right now: Model.StripeChargeHistory won't work because there is no such property in the class AdminChargeHistory.
Also, you have public string ErrorMessage { get; set;] }, that bracket looks like a problem.

Related

Using multiple paginated lists on one HTML page

I'm MVC / Razor pages newbie so bear with me. I would like to display several lists of items on one page. These lists have 100+ items each so they need to be paginated. In Microsofts Entity Framework .net core tutorial I found only 1 pagination per page, so that cannot be used.
I feel like I should be using View Component to achieve this, but I'm quite not sure how to do it. Can anyone help me please?
I'm using Razor pages .net Core, but I'm not against using controller to achieve this
Thanks in advance
My view is:
#page
#model DOOR.Core.Web.Pages.Models.IndexModel
<h2 style="margin-top:20px "><span class="glyphicon glyphicon-compressed"></span> Model #Html.DisplayFor(model => Model.
<h4 class="h4-bold">Tables</h4>
#if (Model.PdModel.FirstOrDefault().PdTables.Count == 0)
{
#:Model doesn't contain any tables
}
else
{
<table class="table table-striped">
<thead>
<th>
Name
</th>
<th>
Description
</th>
<th>
Type
</th>
</thead>
#foreach (var tableItem in Model.PdModel.FirstOrDefault().PdTables.OrderBy(x => x.TableName))
{
<tr>
<td>
<a asp-page="/Tables/Index" asp-route-id="#tableItem.Id" asp-page-handler="LoadTable"><span class="glyphicon glyphicon-list-alt"></span> #tableItem.TableName</a>
</td>
<td>
#tableItem.TableComment
</td>
<td>
#tableItem.TableStereotype
</td>
</tr>
}
</table>
}
<hr />
<h4 class="h4-bold">View</h4>
#if (Model.PdModel.FirstOrDefault().pdViews.Count == 0)
{
#:Model doesn't contain any view
}
else
{
<table class="table table-striped">
<thead>
<th>Name</th>
<th>Description</th>
</thead>
#foreach (var viewitem in Model.PdModel.FirstOrDefault().pdViews.OrderBy(x => x.ViewName))
{
<tr>
<td><a asp-page="/Views/index" asp-page-handler="LoadView" asp-route-id="#viewitem.ID"><i class="glyphicon glyphicon-search"></i> #viewitem.ViewCode</a></td>
<td>#viewitem.ViewComment</td>
</tr>
}
</table>
}
My domain models are:
public class PdModel
{
public int Id { get; set; }
public string ModelCode { get; set; }
...
public ICollection<PdTable> PdTables { get; set; }
public ICollection<PdView> pdViews { get; set; }
}
public class PdTable
{
public int Id { get; set; }
public int ModelId { get; set; }
public string ModelCode { get; set; }
public string TableCode { get; set; }
...
[ForeignKey("ModelId")]
public virtual PdModel PdModels { get; set; }
}
public class PdView
{
public int ID { get; set; }
public string ModelCode { get; set; }
public int ModelID { get; set; }
public string ViewCode { get; set; }
...
[ForeignKey("ModelID")]
public virtual PdModel PdModel { get; set; }
}
My method is:
public PaginatedList<PdModel> PdModel { get; set; }
public async Task OnGetLoadModelAsync(int id, int? pageIndex)
{
IQueryable<PdModel> PdModelsQuer = _context.PdModel.Where(x => x.Id == id)
.Include(x => x.PdTables)
.Include(x => x.pdViews)
PdModel = await PaginatedList<PdModel>.CreateAsync(PdModelsQuer, pageIndex ?? 1, 3);
}
Not the best solution, but try this approach instead: you can create separate tables for each item and then link pagination to each table
Not sure if you have found a solution yet, but I like using this library
https://www.nuget.org/packages/X.PagedList.Mvc.Core/
To paginate different models, just create a viewmodel containing your IPagedList objects.
Here's an example of how to set up the pagination control:
#Html.PagedListPager(
(IPagedList)Model.MyPagedListObject,
page => Url.Action("MyControllerAction", "MyController",
new
{
page,
size = Model.MyPagedListObject.PageSize
}),
PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(
new PagedListRenderOptions
{
MaximumPageNumbersToDisplay = 5,
UlElementClasses = new[] { "pagination" },
ContainerDivClasses = new[] { "pagination-container" },
LiElementClasses = new string[] { "page-item" },
PageClasses = new string[] { "page-link" }
},
new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "MyDivWrapperID"
}))
If the documentation and/or this explanation is unclear I can provide a more in depth example.

UL LI tree, on the client part

How can you build a ul LI tree based on an existing model? On the client side of the application.Nesting can be unlimited
#foreach (var item in Model)
{
<tr>
<th scope="col">#Html.DisplayFor(modelItem => item.Id) </th>
#if (item.ParentId != null)
{
<th scope="col">#Html.DisplayFor(modelItem => item.ParentTitle) </th>
}
else
{
<th scope="col">null </th>
}
<th scope="col">#Html.DisplayFor(modelItem => item.Title) </th>
<th scope="col">#Html.DisplayFor(modelItem => item.Description) </th>
<th scope="col">#Html.DisplayFor(modelItem => item.Created) </th>
</tr>
}
I saw a manual build, just tagging and getting model elements, but is it possible to automate the process somehow?
<ul>
<li>First parent
<ul>
<li>First child
<ul>
Model:
[Table("TestTable", Schema = "dbo")]
public class MyClass
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public DateTime Created { get; set; }
public string Description { get; set; }
}
public class MySecondClass
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public DateTime Created { get; set; }
public string Description { get; set; }
public string ParentTitle { get; set; }
}
I would have had a list of children property on your parent rather than 2 very similar classes, then you would be able to make a hierarchical structure:
public class MyClass
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public DateTime Created { get; set; }
public string Description { get; set; }
public IEnuerable<MyClass> Children { get; set; }
}
Then instead of passing a flat set of classes through as your model, you can build up your hierarchy (in the below, I assumed Model is a list of all your items):
var topLevel = Model.Where(item => !item.HasValue); // or whatever the value is when there is no parent
Then you can loop through this top level to set your children:
foreach (var item in topLevel)
{
item.Children = GetChildren(item.Id, Model);
}
And your Get Children method can be
public static IEnumerable<MyClass> GetChildren(int parentId, IEnumerable<MyClass> allItems)
{
if (parentId.HasValue)
{
var children = allItems.Where(item => item.ParentId.HasValue && item.ParentId.Value.Equals(parentId));
if (children != null && children.Any())
{
foreach (var item in children)
{
item.Children = GetChildren(item.Id, allItems);
}
return children;
}
}
return null;
}
This should help build something then you can have a partial that takes a model of IEnumerable<MyClass> and make it recursive:
#model IEnumerable<MyClass>
#foreach (MyClass item in Model)
{
<ul>
<li>
#item.Title
#if (item.Children != null && item.Children.Any())
{
#Html.Partial("NameOfThisPartial", item.Children)
}
</li>
</ul>
}
And your initial partial call will be:
#Html.Partial("NameOfThisPartial", topLevel)

Display a list in a view MVC 4

I have a model Course, a model Component and a model Evaluation:
public class Course
{
public virtual int CourseId { get; set; }
public virtual string Name { get; set; }
public virtual List<Component> Components { get; set; }
public virtual List<UserProfile> Users { get; set; }
public virtual List<Evaluation> Evaluation { get; set; }
}
public class Component
{
public virtual int ComponentId { get; set; }
public virtual int CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual string NameComp { get; set; }
}
public class Evaluation
{
public virtual int EvaluationId { get; set; }
public virtual int CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual int UserId { get; set; }
public virtual UserProfile User { get; set; }
public virtual int Grade { get; set; }
}
I need to show in a view a table with all the users, all the components created and the grade for each one.
I tried this way:
#model SGP.Models.Course
<table>
<tr>
<th>
Username
</th>
#foreach (var x in Model.Components)
{
<th>
#Html.DisplayFor(modelItem => x.NameComp)
</th>
}
<th></th>
</tr>
#foreach (var item in Model.Evaluation)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.User.UserName)
</td>
#foreach (var x in Model.Components)
{
<td>
#Html.DisplayFor(modelItem => item.Grade)
</td>
}
<td>
</td>
</tr>
}
But this gives me all the components in one column, and i need one column for each component, and a grade for each one:
The code i have gives this:
Username - Component1Component2Component3
Test - 12
Test - 13
Test - 10
(example of result with username and grades)
And i need:
Username - Component1 - Component2 - Component3
Test - 12 - 13 - 10
(example of result with username and grades)
How can i do this? Thanks
The definition of Evaluations in Course should be:
public virtual IGrouping<string, Evaluation> Evaluations { get; set; }
The code should be:
#model SGP.Models.Course
<table>
<tr>
<th>
Username
</th>
<th>
#foreach (var x in Model.Components)
{
#Html.DisplayFor(modelItem => x.NameComp)
}
</th>
<th></th>
</tr>
#foreach (var group in Model.Evaluations)
{
<tr>
<td>
#Html.DisplayFor(modelItem => group.Key)
</td>
#foreach (var item in group)
{
<td>
#Html.DisplayFor(modelItem => item.Grade)
</td>
}
<td>
</td>
}
</tr>
You need to make sure the evaluation is in reference to a course component:
public class Evaluation
{
public virtual int EvaluationId { get; set; }
public virtual int CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual int ComponentId { get; set; }
public virtual Component Component { get; set; }
public virtual int UserId { get; set; }
public virtual UserProfile User { get; set; }
public virtual int Grade { get; set; }
}
Here are some test values:
var users = new List<UserProfile>
{
new UserProfile { UserId = 1, UserName = "Jim" },
new UserProfile { UserId = 2, UserName = "Sam" },
};
var components = new List<Component>
{
new Component { ComponentId = 1, NameComp = "Unit 1" },
new Component { ComponentId = 2, NameComp = "Unit 2" }
};
var course = new Course
{
Users = users,
Components = components.OrderBy(c => c.ComponentId).ToList(),
Evaluation = new List<Evaluation>
{
new Evaluation { User = users[0], ComponentId = components[0].ComponentId, Grade = 87 },
new Evaluation { User = users[0], ComponentId = components[1].ComponentId, Grade = 99 },
new Evaluation { User = users[1], ComponentId = components[0].ComponentId, Grade = 75 },
new Evaluation { User = users[1], ComponentId = components[1].ComponentId, Grade = 65 }
}
};
And following Razor view should do what you need:
#model SGP.Models.Course
<table>
<tr>
<th>
Username
</th>
#foreach (var x in Model.Components)
{
<th>
#Html.DisplayFor(modelItem => x.NameComp)
</th>
}
<th></th>
</tr>
#foreach (var userEvaluation in Model.Evaluation.GroupBy(e => e.User))
{
<tr>
<td>
#Html.DisplayFor(modelItem => userEvaluation.Key.UserName)
</td>
#foreach (var x in Model.Components)
{
<td>
#(userEvaluation.FirstOrDefault(e => e.ComponentId == x.ComponentId)?.Grade)
</td>
}
<td></td>
</tr>
}
Watch out for this model, it has a lot of circular references, which can be problematic if you're using something like Entity Framework.

Get Total of a field in mvc entitymodel 1st

I am trying to get total on my view.
I am confused what should i do? Please help me out..
I am not understanding where should i use query and ofc I need it in my view to show but how?
Model class
namespace BOL1
{
public class ADetailsVm
{
public List<BOL1.tbl_Transiction> Payables { get; set; }
public List<BOL1.tbl_Transiction> Reciveables { get; set; }
}
}
DbContext
public partial class bankingEntities : DbContext
{
public bankingEntities()
: base("name=bankingEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<tbl_Accounts> tbl_Accounts { get; set; }
public virtual DbSet<tbl_Transiction> tbl_Transiction { get; set; }
public virtual DbSet<tbl_TransictionType> tbl_TransictionType { get; set; }
public DbSet<ADetailsVm> ADetailsVm { get; set; }
}
}
Controller
public class Details : Controller
{
private TransictionBs objbs;
public Details()
{
objbs = new TransictionBs();
}
// GET: Shinwari/AccountDetails
[HttpGet]
public ActionResult Index(int accountid)
{
ADetailsVm v = new ADetailsVm();
//Load both the collection properties
v.Payables = objbs.GetALL().Where(p => p.AId == accountid && p.tbl_TransictionType.Type.Contains("Payable")).ToList();
v.Reciveables = objbs.GetALL().Where(r => r.AId==accountid && r.tbl_TransictionType.Type.Contains("Reciveable")).ToList();
return View(v);
View
#model BOL1.ADetailsVm
#{
ViewBag.Title = "Index";
}
<h2>AccountDetails</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table id="Payables" class="table">
<tr>
<th>
Date
</th>
<th>
Discription
</th>
<th>
Amount
</th>
</tr>
#foreach (var item in Model.Payables)
{
<tr>
<td>
#item.Date
</td>
<td>
#item.TDiscription
</td>
<td>
#item.Amount
</td>
</tr>
}
</table>
Use the LINQ Sum extension method on the Amount property(assuming it is of numeric type) of your Payables collection property of the view model.
<h2> #Model.Payables.Sum(s=>s.Amount) </h2>
Or if you do not like adding so much C# code in razor views(like me :)), You may add a new property to store the total in your view model.
public class ADetailsVm
{
public decimal TotalPayableAmount { set;get;}
public List<BOL1.tbl_Transiction> Payables { get; set; }
public List<BOL1.tbl_Transiction> Reciveables { get; set; }
}
and in your action method, call the Sum method and set the value to our new TotalPayableAmount property.
public ActionResult Index(int accountid)
{
var v = new ADetailsVm();
v.Payables = objbs.GetALL().Where(p => p.AId == accountid &&
p.tbl_TransictionType.Type.Contains("Payable")).ToList();
v.Reciveables = objbs.GetALL().Where(r => r.AId == accountid &&
r.tbl_TransictionType.Type.Contains("Reciveable")).ToList();
v.TotalPayableAmount= v.Payables.Sum(s=>s.Amount)
return View(v);
}
and in your view
#model ADetailsVm
<h2>#Model.TotalPayableAmount</h2>

ASP.NET MVC One to Many Database Table Values with List Attribute

My First Table is:
First Table Name: Contacts
ContactID (PK)
FirstName
LastName
Company
Second Table Name: Phones
ContactID (FK)
PhoneType
PhoneNumber
My view Model is
public class ContactVM2
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
public string PhoneType { get; set; }
public string PhoneNumber { get; set; }
}
Repository Class is
public class ContactRepository
{
ContactsDBEntities dbRepo = new ContactsDBEntities();
public List<ContactVM> GetAllContacts()
{
List<ContactVM> ContactViewList = new List<ContactVM>();
var allContacts = dbRepo.Contacts.ToList();
var allPhones = dbRepo.Phones.ToList();
foreach (var cont in allContacts)
{
foreach (var ph in allPhones)
{
if (cont.ContactID == ph.ContactID)
{
ContactViewList.Add(new ContactVM(){
ContactID =cont.ContactID,
FirstName=cont.FirstName,
LastName=cont.LastName,
Company=cont.Company,
PhoneType=ph.PhoneType,
PhoneNumber=ph.PhoneNumber});
}
}
}
return ContactViewList;
}
}
and Controller is
public ActionResult Index()
{
ContactRepository contRepo = new ContactRepository();
var allContacts = contRepo.GetAllContacts().ToList();
return View(allContacts);
}
I have following data in Contacts tables
ContactID FirstName LastName Company
1 Bill Gates Microsoft
and in Phones Table
ContactID PhoneType PhoneNumber
1 Home 1111
1 Office 2222
I am getting following result
1 Bill Gates Home 1111
1 Bill Gates Office 2222
Where Contact details are repeating.
I need following result
1 Bill Gates Home 1111
Office 2222
I have also tried following changes in View
<td style="border:2px solid Blue;">
#{
foreach (var parent in Model.Where(x=>x.ContactID==item.ContactID).GroupBy(m=>m.PhoneNumber))
{
foreach( var itm in parent )
{
#itm.PhoneNumber <br />
}
}
}
</td>
<td style="border:2px solid red;">
#{
foreach (var parent in Model.Where(x=>x.ContactID==item.ContactID).GroupBy(m=>m.PhoneType))
{
foreach( var itm in parent )
{
#itm.PhoneType <br />
}
}
}
</td>
But it still repeats the record again.
Then I tried following changes in ModelView
public List<string> PhoneType { get; set; }
public List<string> PhoneNumber { get; set; }
but did not get results.
Can any one help by giving simplest example as I am at very beginner level.
Code without Phone Iteration in View
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ContactID)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Company)
</td>
<td>
#Html.DisplayFor(modelItem => item.PhoneType)
</td>
<td>
#Html.DisplayFor(modelItem => item.PhoneNumber)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
You should remove the iteration from repository class and create a separate class for Phone number and add the variable of that class in ContactVM2 like the the below model:
public class ContactVM2
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
public List<ContactVM2Phone> PhoneList {get; set;}
}
public class ContactVM2Phone
{
public string PhoneType { get; set; }
public string PhoneNumber { get; set; }
}
Repository class
public class ContactRepository
{
ContactsDBEntities dbRepo = new ContactsDBEntities();
public List<ContactVM> GetAllContacts()
{
List<ContactVM> ContactViewList = new List<ContactVM>();
var allContacts = dbRepo.Contacts.ToList();
var allPhones = dbRepo.Phones.ToList();
foreach (var cont in allContacts)
{
ContactViewList obj= new ContactVM()
obj.ContactID =cont.ContactID;
obj.FirstName=cont.FirstName;
obj.LastName=cont.LastName;
obj.Company=cont.Company;
List<ContactVM2Phone> Phonelist= new List<ContactVM2Phone>();
foreach (var ph in allPhones)
{
if (cont.ContactID == ph.ContactID)
{
Phonelist.Add(new ContactVM2Phone(){
PhoneType=ph.PhoneType,
PhoneNumber=ph.PhoneNumber});
}
}
obj.PhoneList =Phonelist;
ContactViewList.Add(obj);
}
return ContactViewList;
}
}

Resources