How to provide dynamic data for a single view using ViewModels
(first post and fairly new to MVC). I currently have an MVC / C # application where the user selects a list of IDs and then selects a report type (8 possible different reports calling 8 different database views). I pass all these parameters to the controller. Based on the selected report type, I want to fetch the data, send it back to the view, and then display the data in a table / table format.
I tried to send data via ViewBag and ViewData but failed to parse the actual columns / data using @foreach. This is when I decided to try ViewModels.
//My ViewModel....
//I know that I am missing the {get;set;} code which is where I also
// need help with. I need to pass the selected ID to each database view and
// perform additional query requests (i.e. Distinct, Order By).
// Sample query:
// var dd = (from p in _db.Report1 select new { sId = p.ReportID, UserName = p.Submitted_By,
// Balance = p.TotalDebt}).Distinct();
// dd = dd.Where(w => chosenUserIDs.Contains(w.sID));
// dd.OrderBy(p => p.sId).ThenBy(p => p.UserName).ThenBy(p => p.Balance);
public class UserReportsViewModel
{
public List<namespace.report1> Report1 = new List<namespace.report1>();
public List<namespace.report2> Report2 = new List<namespace.report2>();
public List<namespace.report3> Report3 = new List<namespace.report3>();
...
}
//My Controller
UserReportsViewModel UserReportVM = new UserReportsViewModel();
switch (reportType)
{
case "REPORT1":
//Pass the selected ID and get the data back from Report1 db view
// not quite sure how to do this.
break;
case "REPORT2":
break;
case "REPORT3":
break;
default:
break;
}
return View(UserReportsVM);
Am I even on the right track? I also came across something about partial views and had the View / referrence view the correct partial view (?). Older languages were much easier to do this, but I really like MVC / .Net / C #.
As far as my database is concerned, I am using the CodeFirst Entity framework.
source to share
I highly suggest that you have views, viewmodel and action for each report. Just name the correct endpoint based on the requested report on the client.
Or, if you want to do it with a single endpoint (action), specify the view you want to return. If you don't provide a view name, it returns a view based on the name of the action, but you can specify the view to render.
return View("ViewToRender", viewModel);
If you want to get fancy, you can do it in one look. Include layout object in viewmodel with data ... this way you can use one view model. The layout will be a list of "column information fields". Column1 will have this header, this width, etc. It will be associated with GenericReportViewModel.Column1.
From there, you just need to project your data into this generic view model.
source to share
Each model will return unique data with a unique set of columns. user comments above
If so, write your logic in a view like this
@if(model.Report1!=null && model.Report1.Count!=0){
// your logic for report1 goes here or you can also use partial view to render
}
else if(model.Report2!=null && model.Report2.Count!=0)
{
// your logic for report2 goes here or you can also use partial view to render
}
The same goes for all other reports. Hope this helps
source to share
Thanks everyone for your help and guidance. I decided to partially consider. The solution to my question is as follows.
For each report, I fetch the data and immediately save the data to ViewData.
IQueryable<dbViewName> Report8 = _db.dbViewName;
ViewData["qryResults"] = Report8;
...
return View(ViewData["qryResults"]);
Then in the main view, I call the partial view:
@Html.RenderPartial(rt, ViewData["qryResults"]);
Partially my model is a strong type.
@model IQueryable<dbViewName>
This allowed me to list the data in the tables using:
@foreach (var item in Model)
It is clean and easy to implement any additional reports the client may request in the future.
Thanks again everyone for your input.
source to share