I am using asp.net core entity framework. I am trying to print out the results of my query into my html. Here is my code.
This is my .cs file
ViewBag.User_Has_Products = (from user_products in _context.Users_Has_Products
join user in _context.Users on user_products.users_id equals user.id
join product in _context.Products on user_products.products_id equals product.id
select new { name = user.name, product = product.name,
quantity = user_products.quanitity, date = user_products.created_at});
foreach(var item in ViewBag.User_Has_Products)
{
System.Console.WriteLine($"{item.name}"); //this output is correct
}
Here is my .cshtml page
#{
if(ViewBag.User_Has_Products != null)
{
foreach(var item in ViewBag.User_Has_Products)
{
<p>#$"{item.name}"</p> //trying to print it out here
}
}
}
I also tried <p>#item.name</p> but got an object does not contain a definition for name error.
You don't need the string quotes in your .cshtml file, just use it as is, see the following example:
#{
if(ViewBag.User_Has_Products != null)
{
foreach(var item in ViewBag.User_Has_Products)
{
<p>#item.name</p>
}
}
}
But the better recommendation is to build a model and send it to your view, like this:
public class UserProductsViewmodel() {
public string Name { get; set; }
public string Product { get; set; }
public int Quantity { get; set; }
public string Date { get; set;}
}
and use it in your .cs file like this:
ViewBag.User_Has_Products = (from user_products in _context.Users_Has_Products
join user in _context.Users on user_products.users_id equals user.id
join product in _context.Products on user_products.products_id equals product.id
select new UserProductsViewmodel() {
Name = user.name, Product = product.name,
Quantity = user_products.quanitity, Date = user_products.created_at
});
And in your .cshtml like this:
#{
if(ViewBag.User_Has_Products != null)
{
foreach(UserProductsViewmodel item in ViewBag.User_Has_Products)
{
<p>#item.Name</p>
}
}
}
Check this article on Dependency injection into views which will a better way than using ViewBag.
Controller action snippet
public IActionResult GetProducts()
{
var products = (from user_products in _context.Users_Has_Products
join user in _context.Users on user_products.users_id equals user.id
join product in _context.Products on user_products.products_id equals product.id
select new UserProductsViewmodel() {
Name = user.name, Product = product.name,
Quantity = user_products.quanitity, Date = user_products.created_at
});
return View(products);
}
View snippet(.cshtml)
#model IEnumerable<namespace.ProductModel>
...
#foreach (var item in Model)
{
<p>#item.Bar</p>
}
ViewModel
public class ProductModel() {
public string Name { get; set; }
public string Product { get; set; }
public int Quantity { get; set; }
public string Date { get; set;}
}
Related
I have 2 tables:
Staff: (ID, NAME)
Salary: (ID, VALUE)
My problem is:
How could I write in query syntax and method syntax in controller and return to the View(), like this in SQL query:
select a.NAME, b.VALUE
from Staff a, Salary b
where a.ID = b.ID
How could I declare in view like:
#model IEnumerable<Project.Model.xxxx>
This is the way I do with one table in IndexController:
LinQDataContext data = new LinQDataContext();
public ActionResult Index(int id)
{
var staffWithTheirSalary = data.Staff
.Select(a => a)
.Where(a => a.ID == id);
}
Index view:
#model IEnumerable<Project.Model.Staff>
#foreach(var item in Model)
{
#item.Name
}
You can have your view model to be IEnumerable<StaffSalaryViewModel> where StaffSalaryViewModel is:
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public string Name { get; set; }
public decimal Salary { get; set; } // Not sure of the type
}
Then to extract the list:
Using Linq method syntax:
var result = data.Staff
.Join(data.Salary,
staff => staff.ID,
salary => salary.ID,
(staff, salary) => new StaffSalaryViewModel {
StaffId = staff.ID,
Name = staff.NAME,
Salary = salary.VALUE
});
Using Linq query syntax:
var result = from staff in data.Staff
join salary in data.Salary on staff.ID equals salary.ID
select new StaffSalaryViewModel {
StaffId = staff.ID,
Name = staff.NAME,
Salary = salary.VALUE
};
UPDATE
It looks like the VALUE field in your Salary table allows null values. If so just make the corresponding property in your view model nullable, like so (provided it is a decimal type):
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public string Name { get; set; }
public decimal? Salary { get; set; } // Nullable/optional decimal
}
Or if you want to set StaffSalaryViewModel.Salary to 0 If VALUE is null, change your query to have:
Salary = salary.VALUE ?? 0
Because tables are being joined, I prefer using the query syntax. The controller would use the LinQDataContext to get at the data, but when creating the C# Object I would recommend creating a Class that is only used for displaying the data (in the example its called MySalaryModel).
public ActionResult Index(int id)
{
IEnumerable<Project.Model.MySalaryModel> staffWithTheirSalary = from staff in data.Staff
join salary in data.Salary on staff.Id equals salary.Id
select new Project.Model.MySalaryModel
{
Id = staff.Id,
Name = staff.Name,
Salary = salary.Value,
};
return View(staffWithTheirSalary);
}
use ViewModel,
you can create Viewmodel Folder in project and Create class into like this.
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public int SalaryeId { get; set; }
public string StaffName { get; set; }
public string SlaaryName { get; set; }
}
in action :
public ActionResult Index(int id)
{
StaffSalaryViewModel staffWithTheirSalary = (from itemStaff in data.Staff join itemSalary in data.Salary in itemStaff.id equal itemSalary.id where itemSalary.id=id select new StaffSalaryViewModel {Salaryname=itemSalary.Name,StaffName=itemStaff.Name,SalaryId=itemSalary.Id,itemStaff.Id}).ToList();
}
in View
#model IEnumerable<Project.ViewModel.StaffSalaryViewModel>
#foreach(var item in Model)
{
#item.SalaryName
}
i'm trying to pass data(.tolist) in inner join query to viewmodel, to use these data in view that contain also a partial view that needs data from viewModel.
public ActionResult IndexAdmin()
{
int userId = (int)Session["UserID"];
userInfo = _context.UserInfo.Find(userId);
var AllTours= (from p in _context.PostsInfo //Why this doesn't return two records
join r in _context.Region
on p.RegionId equals r.Id
where r.CountryId == 1
select new
{
RegionName = r.CountryId,
ImageName = p.ImageName,
}).Distinct().ToList();
//Here i need to define IndexAdminViewModel to populate tours and userInfo.username
return View(AllTours);
}
This is the IndexAdminViewModel:
public class IndexAdminViewModel
{
public string UserName { get; set; }
public string RegionName{get;set;}
public string ImageName {get;set;}
}
The view(IndexAdmin.cshtml)
#Html.Partial("_BarPartialAdmin", Model)
foreach (var post in Model)
{
<img src="~/images/#post.ImageName" alt="QfirstImage">
<h2>post.RegionName</h2>
}
The partial view will only needs the username to display it for once so i used to pass the model to partial view in order to use the username property, the RegionName and ImageName is a collection so that i can iterate over them and get teh values some way like use them in a table.
My question is how to pass the inner join query results AND theuserinfo.username to viewModel to use them in the view???????
You need to create 2 view models
public class ToursViewModel
{
public string RegionName { get; set; }
public string ImageName {get; set; }
}
public class IndexAdminViewModel
{
public string UserName { get; set; }
public IEnumerable<ToursViewModel> Tours {get;set;}
}
Then in the controller
public ActionResult IndexAdmin()
{
int userId = (int)Session["UserID"];
userInfo = _context.UserInfo.Find(userId);
IEnumerable<ToursViewModel> tours = (
from p in _context.PostsInfo
join r in _context.Region
on p.RegionId equals r.Id
where r.CountryId == 1
select new ToursViewModel
{
RegionName = r.CountryId,
ImageName = p.ImageName
});
IndexAdminViewModel model = new IndexAdminViewModel
{
UserName = userInfo.username,
Tours = tours
};
return View(model);
and in the view
#model IndexAdminViewModel
....
<h1>#Model.UserName</h1>
#foreach (var tour in Model.Tours)
{
<img src="~/images/#tour.ImageName" alt="QfirstImage">
<h2>#tour.RegionName</h2>
}
I you need to pass different objects to the view you basically have two options:
Create a composite class and use that as model
var allTours=
from p in _context.PostsInfo //Why this doesn't return two records
join r in _context.Region
on p.RegionId equals r.Id
where r.CountryId == 1
select new PostAndRegion
{
Region = r.CountryId,
Post= p.ImageName,
};
var model = new MyCompositeModel
{
PostsAndRegions = allTours.ToArray(),
UserInfo = null // or get from where you want to
};
return View(model);
with
public class PostAndRegion
{
public Post Post{get;set;}
public Region Region {get;set;}
}
public class MyCompositeModel
{
public IList<PostAndRegion> PostsAndRegions{get;set;}
public UserInfo MyUserInfo{get;set;}
}
Put some of the data in the ViewBag. see http://www.tutorialsteacher.com/mvc/viewbag-in-asp.net-mvc
I'm trying to get values from userList viewbag.i can't figure out the solution. Error is:
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: 'object' does not contain a definition for 'name'
though in ViewBag.userList contains data (2 objects) which i can see while debugging
#foreach (var aUser in ViewBag.userList)
{
<tr>
<td>#aUser.name</td>
<td>#aUser.username</td>
.....
<td>#Html.ActionLink("Edit", "UserEdit","Users")</td>
<td>#Html.ActionLink("Delete", "UserDelete", "Users")</td>
</tr>
}
I have a superclass and a childclass
superclass
public partial class user
{
public int id { get; set; }
public string name { get; set; }
public string username { get; set; }
...
public string user_role { get; set; }
}
childclass
public class UserSub: user
{
public string CreatedUserName { get; set; }
public string ModifiedUserName { get; set; }
}
In my controller i used linq to get values from database and stored it to Viewbag.userList. My controller function is
public ActionResult UserList()
{
IEnumerable<user> users = null;
users = dbEntities.users.ToList();
if (users != null)
{
var userLists = (from a in users join b in users on a.created_user_id equals b.id select new { a.name, a.username, a.password, a.user_role, a.is_enable, a.is_approved, CreatedUserName = b.name, a.create_time, a.is_android, a.device_id }).ToList();
ViewBag.userList = userLists;
}
return View();
}
tried List<UserSub> users=ViewBag.userList....getting error too
Use a ViewModel to share data between view and controller.
For example, first create the ViewModel:
public class userViewModel{
public int id { get; set; }
public string name { get; set; }
public string username { get; set; }
public string user_role { get; set; }
public string CreatedUserName { get; set; }
public string ModifiedUserName { get; set; }
...
}
You can put all data that you need in your view model... Then, I'll recommend you create a class in your model with all the queries that you need (you have to investigate how to do), but you can get the queries from your controller (if you want).
Well, edit your controller function:
public ActionResult UserList()
{
List<userViewModel> userVM = new List<userViewModel>(); //Important! Don't return all the query, just the data that you need.
IEnumerable<user> users = null;
users = dbEntities.users.ToList();
if (users != null)
{
var userLists = (from a in users join b in users on a.created_user_id equals b.id select new { a.name, a.username, a.password, a.user_role, a.is_enable, a.is_approved, CreatedUserName = b.name, a.create_time, a.is_android, a.device_id }).ToList(); //I'm going to suppose that your query is ok and you get all the data that you need...
foreach (var item in userLists)
{
userVM.Add(new userVM(){
userVM.name = item.name;
userVM.username = item.username;
userVM.user_role = item.user_role;
.......
});
}
}
return View(userVM); //return your view model
}
Finally, modify your view and call the ViewModel userViewModel
#model Model.ViewModel.userViewModel //It depends on the namespace
//Then try something likes this...
#foreach (var aUser in Model)
{
<tr>
<td>#aUser.name</td>
<td>#aUser.username</td>
.....
<td>#Html.ActionLink("Edit", "UserEdit","Users")</td>
<td>#Html.ActionLink("Delete", "UserDelete", "Users")</td>
</tr>
}
That's the idea, improve my answer. ;)
I am working with a action method in which I add a linq query with joins. Now I want to add view for this action method. But the problem is this the linq query is getting data from two entity models and I want to select strongly type view then which class I have to add for this. Here is the Action Method
public ActionResult Marks(int id)
{
var marksjoin = (from a in db.TbStudent
join b in db.TbMarks on a.StudentId equals b.StudentId
select new
{
a.StudentName,
b.StudentId,
b.Hindi,
b.English,
b.SocialStudy,
b.Science,
b.Maths,
b.Total
}).ToList();
// var marks = db.TbMarks.Where(m => m.StudentId == id).SingleOrDefault();
if (marksjoin == null)
{
return RedirectToAction("PostMarks");
}
else
{
return View(marksjoin);
}
Now I am getting the data from two entity models and how can I create a strongly type view for this ?
You need to create a new Type (resulting) and then dump your LINQ output into that Type:-
public class NewType
{
public List<Item> Items1{ get; set; }
public List<Item> Items2{ get; set; }
public string Items3{ get; set; }
............and so on
}
Then pass this 'NewType' as strong type to your view.
Query projection explained
var marksjoin = (from a in db.TbStudent
join b in db.TbMarks on a.StudentId equals b.StudentId
select new StudentType
{
StudentName = b.StudentName,
StudentId = b.StudentId,
// etc
}).ToList();
public class StudentType {
public string StudentName { get; set; }
public int StudentId { get; set; }
// etc...
}
I have a linq query, which is further having a subquery, I want to store the result of that query into a user defined type, my query is
var val = (from emp in Employees
join dept in Departments
on emp.EmployeeID equals dept.EmployeeID
select new Hello
{
EmployeeID = emp.EmployeeID
Spaces = (from order in Orders
join space in SpaceTypes
on order.OrderSpaceTypeID equals space.OrderSpaceTypeID
where order.EmployeeID == emp.EmployeeID group new { order, space } by new { order.OrderSpaceTypeID, space.SpaceTypeCode } into g
select new
{
ID = g.Key.SpaceTypeID,
Code = g.Key.SpaceTypeCode,
Count = g.Count()
})
}).ToList();
Definition for my Hello class is
public class Hello
{
public IEnumerable<World> Spaces { get; set; }
public int PassengerTripID { get; set; }
}
Definition for my World class is
public class World
{
public int ID { get; set; }
public string Code { get; set; }
public int Count { get; set; }
}
You are creating anonymous object but you need to specify type name World
select new World
{
ID = g.Key.SpaceTypeID,
Code = g.Key.SpaceTypeCode,
Count = g.Count()
})