MVC5/C#: Pass LINQ inner Join query to view model - c#

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

Related

Select 2 Column of 2 Table

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
}

Printing output from my linq query in html

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

How to create a strongly type view when I have join in query which I am using in Action method?

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...
}

How to select from two table by id in mvc5

I'm new to MVC5,I had troubles with the problem.
can anybody help me?
I have 2 table, DocMain(Doc_Id,Doc_Title) , DocProduct(Doc_Id,Doc_Content),
I want to select the 2 table content by the same Doc_Id.
And loop them.
Display like:
<ul>
<li>title1content1</li>
<li>title2content2</li>
<li>title3content3</li>
</ul>
....
And how to do it?
//Here is my viewmodel
public class MainProductViewModel
{
public IEnumerable<DocMainListView> DocMainListView { get; set; }
public IEnumerable<DocProductListView> DocProductListView { get; set; }
}
-------------------------------------------------
//Here is my controller
public class DocProductController : Controller
{
private IDocProductRepository repository;
private IDocMainRepository repositoryMain;
public DocProductController(IDocProductRepository docProductRepository, IDocMainRepository docMainRepository)
{
this.repository = docProductRepository;
this.repositoryMain = docMainRepository;
}
public ActionResult List()
{
var products = from docProduct in repository.DocProduct
join docMain in repositoryMain.DocMain
on docProduct.Doc_Id equals docMain.Doc_Id
select new { DocMainTitle = docMain.Doc_Title, DocProductContent = docProduct.DocProduct_Content };
//ViewBag.products = products;
//DocProductListView model = new DocProductListView
//{
// DocProduct = repository.DocProduct
// .Join(repositoryMain.DocMain,
// docProduct => docProduct.Doc_Id,
// docMain => docMain.Doc_Id,
// (docProduct, docMain) => new { a = docMain.Doc_Id, b = docProduct.Doc_Id })
// .OrderByDescending(n => n.)
//};
return View(products);
}
}
I don't know how to write the controller code and View code.
As you want to display the title and content only, so your view model would be
public class MainProductViewModel
{
public IEnumerable<ProductInfo> Products { get; set;}
}
public class ProductInfo
{
public string DocMainTitle { get; set;}
public string DocProductContent { get; set;}
}
And your query would be:
var products = from docProduct in repository.DocProduct
join docMain in repositoryMain.DocMain
on docProduct.Doc_Id equals docMain.Doc_Id
select new ProductInfo { DocMainTitle = docMain.Doc_Title, DocProductContent =
docProduct.DocProduct_Content };
And assign this products to the Products of MainProductViewModel and return to view, then config your view as
#model MainProductViewModel

How to print after join linq query

I have this code:
public ActionResult Index()
{
MembershipUser currentUser = Membership.GetUser();
Guid UserId = (Guid)currentUser.ProviderUserKey;
var users = from m in db.Users
join m2 in db.MyProfiles on m.UserId equals m2.UserId
where m.UserId == UserId
select new{UserName = m.UserName, LastActivityDate = m.LastActivityDate,
Address = m2.Address, City = m2.City, State = m2.State, Zip = m2.Zip};
return View(users);
}
This code is in my Controller, I want to run this query and then print the results into my view, how would I write the view?
//if your question is how to display(Print!) a view for above query then in ActionResult Index()
//1] As as best practise always Create a ViewModel - UserViewModel
public class UserviewModel
{
public string Username {get;set;}
public string Address {get;set;}
}
//2] Assign db.user values to UserviewModel or you can use Automapper
//and 3] then return this viewmodel to view
return View(UserviewModel);
This code cannot work because your LINQ query is returning an anonymous object so you cannot strongly type your view. So the first step would be to define a view model which will represent the information you are willing to display on your view:
public class UserViewModel
{
public string UserName { get; set; }
public DateTime LastActivityDate { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
then in your controller action you would return a collection of this view model:
public ActionResult Index()
{
var currentUser = Membership.GetUser();
var userId = (Guid)currentUser.ProviderUserKey;
var users =
from m in db.Users
join m2 in db.MyProfiles on m.UserId equals m2.UserId
where m.UserId == userId
select new UserViewModel
{
UserName = m.UserName,
LastActivityDate = m.LastActivityDate,
Address = m2.Address,
City = m2.City,
State = m2.State,
Zip = m2.Zip
};
return View(users);
}
and finally in your strongly typed view:
#model IEnumerable<AppName.Models.UserViewModel>
#Html.DisplayForModel()
and in the corresponding display template (~/Views/Shared/DisplayTemplates/UserViewModel.cshtml) which will be rendered for each item of the collection:
#model AppName.Models.UserViewModel
<div>
Username: #Html.DisplayFor(x => x.UserName)<br/>
Last activity: #Html.DisplayFor(x => x.LastActivityDate)<br/>
...
</div>
You need to get the type of users and make a List-View of that type. Easiest way to make a view is simply right-clicking in your controller method and selecting Create View. That'll make sure the routing gets done properly as well.

Categories