Compare two lists and pass it to View - asp.net-core

E-commerce website on ASP.NET Core 3.0
There are two model classes:
Products
Images
The multiple images of a single Product are stored in Images table. I am trying to create an All Products Page, but I am struggling with the logic of matching Image with Product Code and pass it to View which displays all the Products in shop along with thumbnail image from Images.cs and Product Title and its price from Product.cs table. How will I match data from two Model classes and make sure all the matching images and products are displayed relevantly.
Image.cs
public class Image
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ImageID { get; set; }
public string ProductCode { get; set; }
public virtual Product Product { get; set; }
public byte[] Pic { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
}
Product.cs
public class Product
{
public Product()
{
ICollection<Category> Categories = new HashSet<Category>();
ICollection<Image> Images = new HashSet<Image>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductID{ get; set; }
[Required, StringLength(150)]
public string ProductCode{ get; set; }
[Required, StringLength(150)]
public string Title { get; set; }
[StringLength(500)]
public string Description { get; set; }
public int Price { get; set; }
[StringLength(150)]
public string Type { get; set; }
[ForeignKey("Category")]
[Required]
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Image> Images { get; set; }
}
Want to create something like this:

Something like this?
If you have relationships between products and images in database,
var list = _context.Product.Include(x => x.Image).ToList();
If you don't have relationship,
var imageslist = _context.Image;
var list = _context.Product.Select(x => new Product()
{
ProductId = x.ProductId,
Title = x.Title,
Price = x.Price,
Description = x.Description,
Images = imageslist.Where(y => y.ProductCode == x.ProductCode).ToList()
}).ToList();
then pass list to view and use #model List< Products > in your view to display all products.
EDITED 2
Your view page
#model IEnumerable<Product>
#{
foreach (var item in Model)
{
var base64image = Convert.ToBase64String(item.Images.FirstOrDefault().Pic);
<div class="col-xs-6 col-sm-4 col-md-3 col-lg-3">
<table>
<tr>
<td>
<img src="data:image/png;base64,#base64image" height="100">
</td>
</tr>
<tr>
<td>#item.Title</td>
</tr>
<tr>
<td>#item.Price</td>
</tr>
</table>
</div>
}
}

Related

Get lastest record from section using mvc5

I want to show in my home page: All section (all link category and one lastest news record in this section).
Please help me to complete my code.
Thank you so much.
My DbContext class:
public partial class xxDbContext : DbContext
{
public xxDbContext()
: base("name=xxDbConnection") { }
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Section> Sections { get; set; }
public virtual DbSet<News> News { get; set; }
}
public partial class Section
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Category> Categories { get; set; }
}
public partial class Category
{
public int Id { get; set; }
public int SectionId { get; set; }
public string Name { get; set; }
public virtual Section Section { get; set; }
}
public partial class News
{
public int Id { get; set; }
public int CateId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
My controllers
public ActionResult NewsInSec()
{
var model = db.Sections.Where(m => m.Publish).ToList();
return PartialView("NewsInSec", model);
}
My view
#model IEnumerable<xx.Models.Section>
<div>
#foreach (var sect in Model)
{
<ol class="breadcrumb">
<li>#sect.Name</li>
#foreach (var cate in sect.Categories)
{
<li>#cate.Name</li>
}
</ol>
**foreach (var item in sect.Categories.SelectMany(c => c.News).Where(c => c.Publish).OrderByDescending(c => c.CreateDate).Take(4).ToList())
{
<div>
#* News title*#
<h4>#item.Title</h4>
<img src="~/img/news/#item.Image" />
#*Content of lastest news*#
<p>#item.NewsContent</p>
<p>#item.Title</p>
</div>
}**
}
Finally, i want to show section, cate, news as my attached photo.
Please help me to see and fix my code above one more time? Thanks and thanks so much.
You can add navigation property in Category for easy access to News.
public partial class Category
{
public int Id { get; set; }
public int SectionId { get; set; }
...
public virtual List<News> News { get; set; }
}
And select last news for section:
#foreach (var cate in sect.SelectMany(s=>s.Categories.SelectMany(c=>c.News))
.OrderByDescending(n=>n.ID).Take(5))
{
<div>
// Title of lastest news
<h3></h3>
<img src="~/img/...." />
// Content of lastest news
<p></p>
</div>
}
Note: more correct way find last news in your Controller and include result in ViewModel, Like that:
public class SomeViewModel
{
public IEnumerable<Section> Sections {get;set;}
public IEnumerable<News> LastNews{get;set;}
}
Fill this model in controller and pass in view.

#Html.LisboxFor Model Binding for multiple items

My Class is
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set; }
}
Trials is anothetr calss
public partial class Trials
{
public int TrialID { get; set; }
public string Name { get; set; }
public int TrialTyp_RefID { get; set; }
public bool isChk { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
in my view I amn trying to bind the ListBoxFor with Trials inseide the team
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.Trials,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
I cant get any value for Trials calss in the controller ..It shows null but I select multi values from listbox
A multiple select only posts back an array of primitive values. It does not post back a collection of complex objects.
You need a view model with a property to bind the selected Trials
public class TeamVM
{
public int TeamId { get; set; }
....
public int[] SelectedTrials { get; set; }
public SelectList Trials { get; set; } // Assign this in your controller rather than using ViewBag
}
then in you view
#Html.ListBoxFor(m => m.SelectedTrials, Model.Trials)
When you post back, Team.SelectedTrials will contain and array of the selected TrialID values.
I changed the Team class as
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set;
public int[] AuthorisedTrials { get; set; }
}
and in View
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.AuthorisedTrials ,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
and in my controller I was able to get the Vlaues for Selected Trials

Take data from different tables and display it in View Index in mvc4

I have 2 tables Work_table and Employee_table.I want to display emp_id from Work_table and corresponding emp_name from Employee_table in the index view of Employee_table.
my models are:
namespace MvcConQuery.Models
{
[Table("Work_Table")]
public class EnquiryModel
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Int32 Enq_id { get; set; }
[Required]
[Display(Name="Name")]
public string CustomerName { get; set; }
[ReadOnly(true)]
public string Date
{
get
{
DateTime Date = DateTime.Now;
return Date.ToString("yyyy-MM-dd"); ;
}
set{}
}
[Required]
[Display(Name = "Region")]
public string Region { get; set; }
[Required]
[RegularExpression(#"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Entered phone number format is not valid.")]
[Display(Name = "Phone number")]
public string Ph_No { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email_id")]
public string Email_id { get; set; }
[Required]
[Display(Name = "Address")]
public string Address { get; set; }
[Required]
[Display(Name = "Query")]
public string Query { get; set; }
public string Referral { get; set; }
public string Feedback { get; set; }
public string Status { get; set; }
public Int32? Emp_id { get; set; }
public string FollowUpDate { get; set; }
public List<EmployeeModel> Employees { get; set; }
}}
namespace MvcConQuery.Models
{
[Table("Employee_Table")]
public class EmployeeModel
{
[Key,Column(Order=0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
//[ForeignKey("EnquiryModel")]
public Int32 Emp_id { get; set; }
public string Emp_Name{ get; set; }
//[Key,Column(Order=1)]
public string Region { get; set; }
//[ForeignKey("Region")]
public string Emp_PhNo { get; set; }
public string Emp_Address { get; set; }
public List<EnquiryModel> Enquires { get; set; }
}
}
How to write controller?
I stucked when writing the function in controller.
public ActionResult Index()
{
}
Please suggest a solution. thanks in advance.
Regards
I was wrong earlier, I made out from your code that there is a many -to- many relationship between Employee and Work tables. For my convenience, I have used Job as the name for your Work table / model.
I hope that you want to display a list of EmployeeIds along with the corresponding EmployeeNames in the Index View. I have added an extra property called JobName to viewmodel, you can have other properties too.
For that matter, create a ViewModel EmployeeViewModel and bind the index view of your action result with an IEnumerable<EmployeeViewModel>. The definition for EmployeeViewModel can be something like -
public class EmployeeViewModel
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string JobName { get; set; }
//..Other memberVariables..
}
Suppose these are your models -
Employee
public class Employee
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string Address { get; set; }
public virtual ICollection<Job> Jobs { get; set; }
}
And WorkTable, renamed it as Job for my own convenience
public class Job
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int JobId { get; set; }
public string JobName { get; set; }
public JobCategory JobCategory { get; set; }
public int EmployeeId { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
In your Index Action, you create a result set by joining the two tables, bind it to IEnumerable<EmployeeViewModel> and pass that as a model to the view. The View should receive a model of type IEnumerable<EmployeeViewModel> as I mentioned earlier,so you need to query your entities which should be something like -
public ActionResult Index()
{
//..something like this..this is IQueryable..
//...convert this to IEnumerable and send this as the model to ..
//..the Index View as shown below..here you are querying your own tables,
//.. Employee and Job,and binding the result to the EmployeeViewModel which
//.. is passed on to the Index view.
IEnumerable<EmployeeViewModel> model=null;
model = (from e in db.Employees
join j in db.Jobs on e.EmployeeId equals j.EmployeeId
select new EmployeeViewModel
{
EmployeeId = e.EmployeeId,
EmployeeName = e.EmployeeName,
JobName = j.JobName
});
return View(model);
}
Your index view should be something like -
#model IEnumerable<MyApp.Models.EmployeeViewModel>
#{
ViewBag.Title = "Index";
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.EmployeeId)
</th>
<th>
#Html.DisplayNameFor(model => model.EmployeeName)
</th>
<th>
#Html.DisplayNameFor(model => model.JobName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.EmployeeId)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmployeeName)
</td>
<td>
#Html.DisplayFor(modelItem => item.JobName)
</td>
</tr>
}
</table>
In this above solution, I have made an attempt to generate a situation similar to yours and address your concerns. I hope this brings some sort of respite to your worries and helps you move ahead. Take this as a map and try follow the routes to find your own destination/solution. Btw, sorry for this delayed reply. Hope this helps.
This code has something missing select new EmployeeviewModel
model = (from e in db.Employees
join j in db.Jobs on e.EmployeeId equals j.EmployeeId
select new EmployeeViewModel
{
EmployeeId = e.EmployeeId,
EmployeeName = e.EmployeeName,
JobName = j.JobName
});

How to make this razor view working?

in my MVC web apps, this is the models which uses icollection object,
public class EmpProfile
{
public int EmpProfileID { get; set; }
public string EmpName { get; set; }
public string EmpNum { get; set; }
public string ManagerEditor { get; set; }
public string DocCreatedBy { get; set; }
public virtual ICollection<PerfPlan> PerfPlans { get; set; }
public virtual ICollection<ProgReview> ProgReviews { get; set; }
}
and this is PerfPlan model, the other model ProgReviews is similar like this one.
public class PerfPlan
{
public int ID { get; set; }
public int EmpProfileID { get; set; }
public string EmpName { get; set; }
public string EmpNum { get; set; }
public string Title { get; set; }
....
public virtual EmpProfile EmpProfile { get; set; }
}
Basically, it builds one to many relationship between EmpProfile and PerfPlan, ProgReview. So one EmpProfile has 0 or many Performance plan and Progress Review data (model).Now, in my Index razor of EmpProfile, I want to list all PerfPlan and ProgReview which related to each EmpProfile, I build something like this:
#model IEnumerable<PerfM.Models.EmpProfile>
<table>
#foreach (var item in Model)
{
<tr class="#selectedRow">
<td >
#Html.ActionLink(#item.EmpName, "Index", new { id = item.EmpProfileID })
</td>
</tr>
//here I need to list all PerfPlan and ProgReview related to this EmpProfile and list under this row.
Can any expert help me to continue the codes below?
Thanks a lot,
Just use simple foreach loops like this (inside of your foreach loop) :
foreach(var plan in item.PerfPlans)
{
// here you can access your PerfPlan properties like:
<tr>
<td> #plan.Id </td>
<td> #plan.EmpName</td>
<td> #plan.EmpNum </td>
...
</tr>
}
foreach(var review in item.ProgReviews)
{
...
}
And in your Controller don't forget to include your collections:
var profiles = context.EmpProfiles.Include("PerfPlans").Include("ProgReviews");

System.Collections.Generic.IEnumerable<MyBlogSite.Models.BlogPost>' does not contain a definition for 'Categories'

Here is my BlogPost Model class:
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; }
[AllowHtml]
public string ShortDescription { get; set; }
[AllowHtml]
public string PostBody { get; set; }
public string Meta { get; set; }
public string UrlSlug { get; set; }
public DateTime PostedOn { get; set; }
public DateTime? Modified { get; set; }
public virtual ICollection<BlogPostCategory> Categories { get; set; }
public virtual ICollection<BlogPostTag> Tags { get; set; }
}
Here is my BlogPostCategory Model class:
public class BlogPostCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string UrlSlug { get; set; }
public string Description { get; set; }
// Decared virtual because the data must be returned from another table.
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}
Each class belongs to a separate Controller/View.
Finally, here is the top port of the Index View for Blog:
#model IEnumerable<MyBlogSite.Models.BlogPost>
#{
ViewBag.Title = "Index";
}
#Html.RenderPartial("~/Views/Category/_Categories.cshtml", Model.Categories );
<p>
#Html.ActionLink("New Blog Post", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
....
In the View where Model.Categories is being passed in is where I am getting the exception from the title of this post. It seems to me that I have defined Categories within the BlogPost Model. What am I doing wrong?
The Model on your Razor page is an IEnumerable<MyBlogSite.Models.BlogPost>. It seems you're trying to display the information about each of the items in your collection. If so, then you can loop through them or create a display/editor template and use #Html.DisplayFor(x => x) or #Html.EditorFor(x => x), respectively.
#foreach(var post in Model) {
<p>Do stuff here with the local "post" variable.</p>
}
Here's a link to Scott Gu's blog talking about the #model directive in Razor views.