Mvc4 how can i use 2 tables in a single view - asp.net

This is an ASP.NET MVC4 project with Entity Framework.
I need to use 2 tables in single view
I have 2 tables in my database (Budgets and Products).
My Models
Budget.cs
public class Budget
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public decimal Value { get; set; }
public int BudgetId { get; set; }
}
BpDb
public class BpDb:DbContext
{
public DbSet<Budget> Budgets { get; set; }
public DbSet<Product> Products { get; set; }
}
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public List<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I need something about Controller to get ProdName (Title from table products)
public class HomeController : Controller
{
BpDb _db = new BpDb();
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
return View(model);
}
}
I need a way to get a list of products Title when the BudgetId = ID (1 Budget can have more than 1 Products)
And my Index is like:
#model IEnumerable<MvcGg.Models.MasterBP>
#foreach (var item in Model)
{
<div>
<h4>#item.Title</h4>
#foreach (var product in item.ProdName)
{
#(product.Title.ToString());
}
Values:#item.CountOfValues
</div>
}

It sounds like (correct me if I am wrong) you want to access two sets of entities in your view model?
Then something along these lines will do:
public class BudgetsViewModel
{
public IEnumerable<MasterBP> MasterBps { get;set; }
public IEnumerable<Product> Products { get;set;}
}
And then you just retrieve all the data and populate the viewmodel and pass it down.
...
var budgets =_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
var model = new BudgetsViewModel()
{
MasterBps = budgets
//Products here
}
return View(model);
...
However it would be better if you made some form of service layer to handle the retrieving on entities and the mapping to view models instead of having all this logic in your controller.

finally this solve my problem,
Model:
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I replaced List<> with IEnumerable<>
Controller:
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).AsEnumerable(),
CountOfValues = r.Products.Count()
});
return View(model);
}
In addition i have change ToList() in AsEnumerable() and now i can see my result using this
View:
Index
#foreach (var item in Model)
{
<div>
#item.Title
<ul>
#foreach (var prod in item.ProdName)
{
<li>#prod.Title</li>
}
</ul>
<hr />
</div>
}

Related

How do I list an indefinite number of nested categories and subcategories with a partial view.(.NET CORE 5.0)

I am new to programming. I want to list the categories whose nested number is not clear. As a result of my research, I decided that I could do it in a single Database table. I thought I should use a recursive structure for this and decided to use partialview for it.
DB Entity
public class Categories {
public int ID { get; set; }
public int ParentCatID { get; set; }
public string CategoryName { get; set; }
public string Instruction { get; set; }
}
PartialView I am trying to write
Can I do it without using PartialView?
I want to achieve this output
class
public class Categories
{
public int ID { get; set; }
public int? ParentCatID { get; set; }
public Categories ParentCat { get; set; }
public string CategoryName { get; set; }
public string Instruction { get; set; }
public IList<Categories> Children { get; protected set; } = new List<Categories>();
}
ViewModel
public class CategoriesViewModel
{
public CategoriesViewModel()
{
ChildItems = new List<CategoriesViewModel>();
}
public long ID { get; set; }
public string CategoryName { get; set; }
public string Instruction { get; set; }
public CategoriesViewModel ParentCatID { get; set; }
public IList<CategoriesViewModel> ChildItems { get; set; }
public void AddChildItem(CategoriesViewModel childItem)
{
childItem.ParentCatID = this;
ChildItems.Add(childItem);
}
}
controller
public IActionResult List()
{
var categories = _context.ToList(); // example
var categoryItems = new List<CategoriesViewModel>();
var topCategories = categories.Where(x => !x.ParentCatID.HasValue);
foreach (var category in topCategories)
{
var categoryMenuItem = Map(category);
categoryItems.Add(categoryMenuItem);
}
return View(categoryItems);
}
private CategoriesViewModel Map(Categories category)
{
var categoryMenuItem = new CategoriesViewModel
{
ID = category.ID,
CategoryName = category.CategoryName,
Instruction = category.Instruction
};
var childCategories = category.Children;
foreach (var childCategory in childCategories)
{
var childCategoryMenuItem = Map(childCategory);
categoryMenuItem.AddChildItem(childCategoryMenuItem);
}
return categoryMenuItem;
}
view
#model IEnumerable<CategoriesViewModel>
#foreach (var item in Model)
{
if (item.ChildItems.Any())
{
<li>
<span>#item.CategoryName</span>
<ul class="dropdown">
<li>
#foreach (var childItem in item.ChildItems)
{
<span>#childItem.CategoryName</span>
}
</li>
</ul>
</li>
}
else
{
<li><span>#item.CategoryName</span></li>
}
}

How to include another table to view its data in Views in asp.net mvc

I have this code -
var add = (from h in db.Hotels
where h.Address.Contains(hotels.Address)
select h).Take(2);
ViewBag.Related = add;
Now, in the View, I want to display the images, so I'm using this code -
<img src="~/img/#item.FirstOrDefault().Image" />
This is giving me this error -
'System.Data.Entity.DynamicProxies.Hotels_D1EE6FD2E11BD1D9436F26FEA6336CFE76F33C59111E2ABC7C1BBE456FF61C23' does not contain a definition for 'FirstOrDefault'
I've tried using 'joins' also but same error occurs. Please help me out in this! :(
My Hotels class -
public class Hotels
{
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
[StringLength(8)]
public string PinCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string FilledBy { get; set; }
public DateTime DateAdded { get; set; }
//public int ImageId { get; set; }
public int TotalRooms { get; set; }
public bool Available { get; set; }
public virtual ICollection <Rooms> Rooms { get; set; }
public virtual ICollection <Images> Images { get; set; }
public virtual ICollection<Ameneties> Ameneties { get; set; }
public virtual ICollection <Bookings> Bookings { get; set; }
public virtual ICollection<NearByLocations> Nearby { get; set; }
public virtual ICollection<Ratings> Ratings { get; set; }
public virtual ICollection<RoomType> RoomTypes { get; set; }
public virtual ICollection<CustomerReviews> Reviews { get; set; }
public virtual ICollection<HotelRules> HotelRules { get; set; }
}
My Images class -
public class Images
{
[ScaffoldColumn(false)]
public int id { get; set; }
public string Image { get; set; }
public int? HotelId { get; set; }
public virtual Hotels Hotels { get; set; }
//public ICollection<Hotels> Hotels { get; set; }
}
I have used this type of collections...
This is my Details View Controller code -
public ActionResult Details(int? id)
{
IEnumerable<Images> galleries = (from gallery in db.Images
where gallery.Hotels.Id == id
select gallery);
ViewBag.Images = galleries;
ViewBag.ImgCount = galleries.Count();
IEnumerable<Ameneties> ameneties = (from a in db.Ameneties
where a.Hotels.Id == id
select a);
ViewBag.Ameneties = ameneties;
IQueryable<Rooms> rooms = (from room in db.Rooms
where room.Hotels.Id == id
select room);
var ratings = (from rating in db.Ratings
where rating.Hotels.Id == id
select rating.Points);
ViewBag.Ratings = ratings;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Hotels hotels = db.Hotels.Find(id);
if (hotels == null)
{
return HttpNotFound();
}
var add = db.Hotels.Include("Images").Where(h => h.Address.Contains(hotels.Address))
.Select(h => h)
.Take(2)
.ToList();
var model = new MyViewModel { Hotels = add };
ViewBag.Reviews = hotels.Reviews;
ViewBag.Ratings = hotels.Ratings;
ViewBag.NearBy = hotels.Nearby;
ViewBag.RoomTypes = hotels.RoomTypes;
ViewBag.Rules = hotels.HotelRules;
return View(hotels);
}
Could you add ToList() at the end of the query?
var add = (from h in db.Hotels
where h.Address.Contains(hotels.Address)
select h).Take(2)
.ToList();
ViewBag.Related = add;
Then you could call item.Images.FirstOrDefault()?.Image.
#foreach (var item in ViewBag.Related)
{
<img src="~/img/#item.Images.FirstOrDefault().Image" />
}
If it still doesn't work, you will need to explicitly load Image when you query Hotel. For example,
public IActionResult Index()
{
var add = db.Hotels
.Include("Images")
.Where(h => h.Address.Contains(hotels.Address))
.Select(h => h)
.Take(2)
.ToList();
var model = new MyViewModel { Hotels = add };
return View(model);
}
View
#model YourNameSpace.Models.MyViewModel
#foreach (var item in Model.Hotels)
{
<img src="~/img/#item.Images.FirstOrDefault().Image" />
}
Model
public class MyViewModel
{
public List<Hotels> Hotels { get; set; }
}

select list by specific id using two models in one view- Asp.Net MVC Razor

Classes
public partial class Category
{
public Category()
{
this.SubCategories = new HashSet<SubCategory>();
}
public int Cat_id { get; set; }
public string Cat_Name { get; set; }
public string Cat_Desc { get; set; }
public virtual ICollection<SubCategory> SubCategories { get; set; }
}
public partial class SubCategory
{
public int SubCat_id { get; set; }
public byte SubCat_icon { get; set; }
public string SubCat_Name { get; set; }
public string SubCat_Desc { get; set; }
public int Cat_id { get; set; }
public virtual Category Category { get; set; }
}
Controller
public ActionResult Index()
{
List<object> myModel = new List<object>();
myModel.Add(db.Categories.ToList());
myModel.Add(db.SubCategories.ToList());
return View(myModel);
}
View
#model IEnumerable<object>
#{
List<ProjName.Models.Category> IstCategory = Model.ToList()[0] as List<ProjName.Models.Category>;
List<ProjName.Models.SubCategory> IstSubCategory = Model.ToList()[1] as List<ProjName.Models.SubCategory>;
}
<h1>Category</h1>
#foreach(var item in IstCategory)
{
<div>#item.Cat_Name</div><br />
}
<hr />
<h1>SubCategory</h1>
#foreach(var item in IstSubCategory)
{
<div>#item.SubCat_Name</div><br />
}
How to pass distinct/specific id in foreach() loop and where condition, when data is selected in list?
Are you trying to achieve this? Each Category has its SubCategories list.
<h1>Category</h1>
#foreach(var cat in IstCategory)
{
<div>#cat.Cat_Name</div><br />
<hr />
<h1>SubCategory</h1>
#foreach(var sub_cat in IstSubCategory.Where(s => s.Cat_id == cat.Cat_id))
{
<div>#sub_cat.SubCat_Name</div><br />
}
}

Retrieve list from object in Database

I want to send a list of names contained in a Database using asp.net
These are my two objects:
public class Shop
{
public int ID { get; set; }
public string Country { get; set; }
public List<Item> Items{ get; set; }
}
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
}
I want to set a get controller in order to retrieve a list of items.
I did something like this:
public IEnumerable<Item> Get(int id)
{
var items= new List<Item>();
var shop= new Shop();
using (var systemDB = new ShopsDB())
{
it = systemDB.Shops.Where(s => s.ID == id).FirstOrDefault<Shop>();
items = it.Items;
}
return items;
}
This return <ArrayOfItem i:nil="true"/>.
I want to get the complete list of Items for one shop (e.g. shop with ID=1)
This will return you the list
using (var systemDB = new ShopsDB())
{
lab = systemDB.Shops.Where(s => s.ID == id).ToList();
items = lab.Items;
}
I solved modifying the Item object:
public class Shop
{
public int ID { get; set; }
public string Country { get; set; }
public List<Item> Items{ get; set; }
}
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public int ShopID { get; set; }
}
And set a query to select the ShopID

MVC 5 Multiple Models in a Single View

Could somebody please provide an example of how to combine two models within one view?
Currently I have a page called RecordCard which contains:
#model IEnumerable<WebApplication1.Models.Weight>
This is provided by the following code in the AccountController:
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
return View(weightModel);
}
The RecordCard page also contains a form which is bound to the following class:
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
However, these are two individual models with different purposes, so how do I combine to a single model that contains an IEnumerable list and set of form elements that will ultimately post to the AccountController correctly to add a record to the database using the following code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(Weight Model)
{
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return View(Model);
}
I have included the Weight class below:
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
Also here is the WebApplication1Entities class which declares the Weight table as Weights:
public partial class WebApplication1Entities : DbContext
{
public WebApplication1Entities()
: base("name=WebApplication1Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Weight> Weights { get; set; }
}
Please explain what needs to be modified and how, no matter what I try to read, follow and implement, I seem to be missing something.
Any help would be much appreciated :-)
I would say this is good example of using ViewModel here. I would suggest something like -
Create ViewModel with the composition of the two classes
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
....
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
.....
public class WeightViewModel
{
public IList<AddWeightModel> AddWeightModel { get; set; }
public Weight Weight { get; set; }
}
Then change your view to accept the view models -
#model WeightViewModel
Finally modify your controller to cope with the change -
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
var viewModel = new WeightViewModel
{
Weight = weightModel,
AddWeightModel = new List<AddWeightModel>(){}
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(WeightViewModel viewModel)
{
Weight Model = viewModel.Weight;
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return RedirectToAction("RecordCard");
}
I've tackled this before, can came to an elegant solution.
First, you'd want to setup your main classes to send, as well as a 'holder' class to store them to eventually send to a view.
As you probably found out, this is because a view can't have multiple models sent to it.
public class WebsiteTheme
{
public string Color { get;set; }
public string Title { get;set; }
public WebsiteTheme() {
Color = "blue";
Title = "test website";
}
}
public class User
{
public string Name { get;set; }
public string Gender { get;set; }
public User() {
Name = "Anonymous";
Gender = "Unspecified";
}
}
public class ToPage
{
public WebsiteTheme WebsiteTheme{ get; set; }
public User User { get; set; }
public ToPage() {
websiteTheme = new WebsiteTheme();
user = new User();
}
}
This will allow you to send any amount of classes to your page.
Then, in your controller, you'd want to populate those classes. Make sure to initialise them all first, then set the populated classes to your holder class.
WebsiteTheme websiteTheme = new WebsiteTheme();
websiteTheme.Color = "orange";
User user = new User();
user.Name = "Darren";
ToPage toPage = new ToPage();
toPage.User = user;
toPage.WebsiteTheme = websiteTheme;
return View(toPage);
In your view, you'd call them in any way you want to. But make sure to use HolderModel.SpecifiedModel in every case.
#model WebApplication1.Models.ToPage
#Html.DisplayFor(model => model.User.Name)
I did a compound model like this:
public class CompoundModel
{
public SearchModel SearchModel { get; set; }
public QueryResultRow ResultModel { get; set; }
}
public class QueryResultRow
{
[DisplayName("Id")]
public long id { get; set; }
[DisplayName("Importdatum")]
public System.DateTime importdate { get; set; }
[DisplayName("Mandant")]
public int indexBMClient { get; set; }
}
public class SearchModel
{
[Required]
[DataType(DataType.Date)]
[Display(Name = "Zeitraum von")]
public DateTime dateFrom { get; set; }
[Display(Name = "Terminal-ID")]
public string tid { get; set; }
[Display(Name = "Belegnummer")]
public string receiptnumber { get; set; }
}
In the view header:
#model MyProject_aspmvc.Models.CompoundModel
And get data access from the SearchModel, for example:
model => model.SearchModel.tid
and data access from the ResultModel, for example:
model => model.ResultModel.importdate

Resources