Loop through list of objects inside object - c#

I'm using mvc and I'm passing the class called DataModel as my model to the view:
public class DataModel
{
public List<ServerStats> statsPerMonthPerServer { get; set; }
}
And here is the class ServerStats:
public class ServerStats
{
public string ServerID { get; set; }
public List<ColumnData> ServerMonthStats { get; set; }
}
And here is the class ColumnData:
public class ColumnData
{
public string Date { get; set; }
public double Sum { get; set; }
}
I have managed to build my ModelData object, if I debug it, it looks like the information I want is in it, but I can not manage to print it out from the view. This is what I've tried to do:
View:
#model IEnumerable<WebApp.Models.DataModel>
#foreach (var server in Model)
{
foreach (var month in server.statsPerMonthPerServer)
{
#month.ServerID
foreach (var column in month.ServerMonthStats)
{
#column.Date <br />
#column.Sum <br />
}
}
}
And the controller where I build the DataModel and send it to the view:
DataModel dm = new DataModel();
dm.statsPerMonthPerServer = new List<ServerStats>();
foreach (var row in serverStats)
{
ServerStats ss = new ServerStats();
ss.ServerID = row.ServerID;
ss.ServerMonthStats = new List<ColumnData>();
ColumnData cd = new ColumnData();
cd.Date = row.Year.ToString() + "-" + row.Month.ToString();
cd.Sum = row.ServerSum;
ss.ServerMonthStats.Add(cd);
dm.statsPerMonthPerServer.Add(ss);
}
return View(dm);
The error I get:
The model item passed into the dictionary is of type 'WebApp.Models.DataModel', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[WebApp.Models.DataModel]'.
I'm using lists but it says this is a dictionary, but I assume it is talking about my lists. I've read some about the IEnumerable interface. Do I have to implement it on all the classes except DataModel? I thought the model decleration on the top of the view took care of this? Any help would be preciated!

The error message is pretty clear. Your view is strongly typed to IEnumerable<DataModel> but from your controller action you passed only a single DataModel instance to the view. I guess you meant this:
#model WebApp.Models.DataModel
#foreach (var month in Model.statsPerMonthPerServer)
{
<h3>#month.ServerID</h3>
#foreach (var column in month.ServerMonthStats)
{
#column.Date <br />
#column.Sum <br />
}
}

Related

ASP.NET CORE Error when trying to add a List of Objects to an Object with a list in it

I have a ASP.Net Core project that I'm working on. So I have a Linq call that gets the information from the database and sends it back to the Controller, no problem there. When I send this data to the View I get an error
The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[PhotoUploader.Models.UnitPictures]', but this ViewDataDictionary instance requires a model item of type 'PhotoUploader.Models.FileViewModel'.
Now I know why this is, Its because the model types don't match from the controller to the View. My question is, how do I assign the UnitPictures to the FileViewModel list I've created inside of it.
Model
public class UnitPictures
{
public long ImageId { get; set; }
public string FileName { get; set; }
public string FileLocation { get; set; }
public int SortOrder { get; set; }
}
View Model
public class FileViewModel
{
public FileViewModel()
{
UnitPicturesList = new List<UnitPictures>();
}
//Other Fields here
public List<UnitPictures> UnitPicturesList { get; set; }
}
Method Call return data of type UnitPictures
private List<UnitPictures> GetImages(long Id)
{
var images = (from a in _db.Images
join b in _db.AutoImage
on a.ImageId equals b.ImageId
where b.Id == Id
select new UnitPictures
{
FileLocation = "",
FileName = a.FileName,
SortOrder = 0,
ImageId = a.ImageId
}).ToList();
return images;
}
Controller
public IActionResult UnitImages(long Id, long unitId)
{
var images = GetImages(Id);
return View(images);
}
View
#model FileViewModel
<div class="row">
<div class="col-lg-4 col-md-12 mb-4 mb-lg-0">
#for (var i = 0; i < Model.UnitPicturesList.Count; i++)
{
<img
src="https://mdbcdn.b-cdn.net/img/Photos/Horizontal/Nature/4-col/img%20(73).webp"
class="w-100 shadow-1-strong rounded mb-4"
alt="Boat on Calm Water"
/>
}
</div>
If your viewmodel is of type FileViewModel, that's what you need to pass to View:
public IActionResult UnitImages(long Id, long unitId)
{
FileViewModel viewModel = new(){ UnitPicturesList = GetImages(Id) };
return View(viewModel);
}
Since you have a mutable UnitPicturesList property, just assigning it directly like this will work.
You create an instance of the view model, populate the relevant members and return that to the view.
public IActionResult UnitImages(long Id, long unitId)
var images = GetImages(Id);
FileViewModel model = new FileViewModel() {
UnitPicturesList = images
};
return View(model);
}
The will allow the view to now properly bind to the matching members in the ViewDataDictionary
You need to create an instance of FileViewModel and then assign the property UnitPictureList to the result of GetImages. Finally you return the View passing the instance of FileViewModel
public IActionResult UnitImages(long Id, long unitId)
{
var fileModel = new FileViewModel();
fileModel.UnitPicturesList = GetImages(Id);
return View(fileModel);
}
Can be shortened even more with
var fileModel = new FileViewModel{UnitPicturesList=GetImages(Id)};

How to display the List of object to view

My Model Class
public class DisplaceModel
{
public string Name { get; set; }
public string Address { get; set; }
public string Type { get; set; }
public string Rating { get; set; }
public string PhotoReference { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
public class DisplaceModelInformation
{
public List<DisplaceModel> Dispaylist { get; set; }
public DisplaceModelInformation()
{
Dispaylist = new List<DisplaceModel>();
}
}
And My Controller
var Display = new DisplaceModelInformation();
XElement generalElement = xdoc1.Element("PlaceSearchResponse");
Display.Dispaylist = (from c in xdoc1.Descendants("result")
select new DisplaceModel()
{
Name = Convert.ToString(c.Element("name").Value),
Address = Convert.ToString(c.Element("vicinity").Value),
Type = keyword,
Rating = (c.Element("rating") != null ? Convert.ToString(c.Element("rating").Value) :null),
PhotoReference = (c.Element("photo") != null ? Convert.ToString(c.Element("photo").Element("photo_reference").Value) : null),
Width = (c.Element("photo") != null ? Convert.ToInt16(c.Element("photo").Element("width").Value) : 0),
Height = (c.Element("photo") != null ? Convert.ToInt16(c.Element("photo").Element("height").Value) : 0)
}).ToList<DisplaceModel>();
return View(Display);
Now I try to display my list of object to view, I tried but I really dont know how to display in mvc view(cshtml) file
My MVC View
#model IEnumerable<FindLocation.Models.DisplaceModelInformation>
#using (Html.BeginForm())
{
<table>
<tbody>
<tr>
<th>NAME</th>
<th>ADDRESS</th>
<th>RATING</th>
</tr>
#foreach (var element in Model)
{
if (element.Dispaylist.Count > 0 )
{
<tr>
<#*td>#element.Dispaylist from c </td>
<td>#Display.Address</td>
<td>#Display.Rating</td>*#
</tr>
}
}
</tbody>
</table>
I am new to UI and I try to extract the list of object but i dont know how to list the object. so please help me....and thanks for your help
Part of the trouble might be coming from the type difference between what you're passing to the view from the controller (DisplaceModelInformation) and the #model definition in the view itself (IEnumerable<DisplaceModelInformation>). Changing one to match the other should help.
I think you have the right idea with #foreach. If your model is an IEnumerable, you would need to iterate over that collection first, then iterate over the DisplayList collection in another inner loop.
The answers to the following question seem to have some good examples of what you're trying to accomplish:
Foreach in a Foreach in MVC View
There are two issues in your code:
In your Controller, you need to return View(new List<DisplaceModelInformation> { Display });, because you specified an IEnumerable model in your View: #model IEnumerable<FindLocation.Models.DisplaceModelInformation>
Use foreach to display each table row:
#foreach (var element in Model)
{
if (element.Dispaylist.Count > 0)
{
foreach (var Display in element.Dispaylist)
{
<tr>
<td>#Display.Name</td>
<td>#Display.Address</td>
<td>#Display.Rating</td>
</tr>
}
}
}

Create dynamic view in MVC as list

I want to make dynamic view that show list of entity properties.
I create these models
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class EmployeeModel : PersonModel
{
public string CompanyName { get; set; }
}
public class StudentModel : PersonModel
{
public string SchoolName { get; set; }
}
I want one view that show list, the view dynamically generated
for examples columns and data appear in list.
Example when open employee I will show following:
and when Open student I will show following:
what easiest way to make my view dynamical and contain the columns and data I want?
I hope this makes as much sense as I think it does!
As List<PersonModel>, List<EmployeeModel> and List<StudentModel> are actually considered completely different, you will need a way to overcome that issue. I use a generic container class:
public interface IGenericContainer
{
dynamic Data { get; }
}
public class GenericContainer<T> : IGenericContainer
{
T _Data { get; set; }
public GenericContainer(T data)
{
_Data = data;
}
dynamic IGenericContainer.Data
{
get { return _Data; }
}
}
public class GenericContainer
{
public static GenericContainer<T> Create<T>(T data)
{
return new GenericContainer<T>(data);
}
}
You then need a generic view that uses this. Put this in Shared/DisplayTemplates/GenericGrid.cshtml
#using System.Reflection;
#using System.Text;
#{
Layout = null;
}
#model IGenericContainer
#{
IEnumerable<PropertyInfo> properties = null;
if (Model.Data.Count > 0)
{
properties = Model.Data[0].GetType().GetProperties();
}
}
<div>
#if (properties != null)
{
<table>
<thead>
<tr>
#foreach (var prop in properties)
{
<td>#prop.Name</td>
}
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Data.Count; i++)
{
<tr>
#foreach (var prop in properties)
{
<td>#prop.GetValue(Model.Data[i])</td>
}
</tr>
}
</tbody>
</table>
}
</div>
To use this you will need to add this to your view:
#Html.DisplayFor(m => GenericContainer.Create(Model.PersonList), "GenericGrid")
And PersonList is a property in your model of type List<PersonModel> or a list of any of your models.
I'm not really sure if I have understood your requirements properly, but if you wanted to display each property of your model dynamically as a column header, then you could try the following:
In your view, you can call the GetProperties method on the type and recursively add a column for each property:
#model PersonModel
#if (Model != null)
{
<table style="width:100%">
<tr>
#foreach (string property in Model.GetType().GetProperties().Select(x => x.Name).ToList())
{
<td>#property</td>
}
</tr>
</table>
}
You can use this example to populate the header columns of a table before you populate the rows. To populate the rows you would need a list of PersonModel and do a foreach on this similar to what I have shown you for the column headers.
Hope that helps.

Display List in a View MVC

I'm trying to display the list I made in my view but keep getting : "The model item passed into the dictionary is of type 'System.Collections.Generic.List1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[Standings.Models.Teams]'."
My Controller:
public class HomeController : Controller
{
Teams tm = new Teams();
public ActionResult Index()
{
var model = tm.Name.ToList();
model.Add("Manchester United");
model.Add("Chelsea");
model.Add("Manchester City");
model.Add("Arsenal");
model.Add("Liverpool");
model.Add("Tottenham");
return View(model);
}
My model:
public class Teams
{
public int Position { get; set; }
public string HomeGround {get; set;}
public string NickName {get; set;}
public int Founded { get; set; }
public List<string> Name = new List<string>();
}
My view:
#model IEnumerable<Standings.Models.Teams>
#{
ViewBag.Title = "Standings";
}
#foreach (var item in Model)
{
<div>
#item.Name
<hr />
</div>
}
Any help would be appreciated :)
Your action method considers model type asList<string>. But, in your view you are waiting for IEnumerable<Standings.Models.Teams>.
You can solve this problem with changing the model in your view to List<string>.
But, the best approach would be to return IEnumerable<Standings.Models.Teams> as a model from your action method. Then you haven't to change model type in your view.
But, in my opinion your models are not correctly implemented. I suggest you to change it as:
public class Team
{
public int Position { get; set; }
public string HomeGround {get; set;}
public string NickName {get; set;}
public int Founded { get; set; }
public string Name { get; set; }
}
Then you must change your action method as:
public ActionResult Index()
{
var model = new List<Team>();
model.Add(new Team { Name = "MU"});
model.Add(new Team { Name = "Chelsea"});
...
return View(model);
}
And, your view:
#model IEnumerable<Standings.Models.Team>
#{
ViewBag.Title = "Standings";
}
#foreach (var item in Model)
{
<div>
#item.Name
<hr />
</div>
}
You are passing wrong mode to you view. Your view is looking for #model IEnumerable<Standings.Models.Teams> and you are passing var model = tm.Name.ToList(); name list. You have to pass list of Teams.
You have to pass following model
var model = new List<Teams>();
model.Add(new Teams { Name = new List<string>(){"Sky","ABC"}});
model.Add(new Teams { Name = new List<string>(){"John","XYZ"} });
return View(model);

How to Pass Details Model from Controller to View

I am accessing Data in Controller using a WCF Service.
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
return View();
}
Now how to pass the orderdetails from Controller to view and how to access them in View.
Edit:
I have a Model :
public class OrderDetails
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal UnitPrice { get; set; }
public int quanity { get; set; }
public decimal Discount { get; set; }
}
and _proxy.GetProductDetails(null) returns List<ServiceType.OrderDetails>
Do I need a Local Model at all in this scenario?
How do I display the List values in a table in my view?
Edit2:
public class AutoMapperConfig
{
public static void Configure()
{
Mapper.Map(ServiceOrders.OrderDetails, NorthWindMVCWCF.Models.OrderDetails);
}
}
Now getting the Error
'NorthWindMVCWCF.ServiceOrders.OrderDetails' is a 'type', which is not valid in the given context
'NorthWindMVCWCF.Models.OrderDetails' is a 'type', which is not valid in the given context
I prefer to create view models, I would do it as follows:
Create View Models
public class OrderDetailViewModel
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public decimal UnitPrice { get; set; }
public int Quanity { get; set; }
public decimal Discount { get; set; }
}
public class OrderDetailsViewModel
{
public OrderDetailsViewModel()
{
OrderDetails = new List<OrderDetailsViewModel>();
}
public List<OrderDetailsViewModel> OrderDetails { get; set; }
}
Manual projection
You could create an OrderDetails view model and project an instance manually as follows:
var orderDetailsViewModel = new OrderDetailsViewModel();
foreach(var orderdetail in orderDetails)
{
orderDetailsViewModel.Add(new OrderDetailsViewModel { OrderId = orderDetail.OrderId, ProductId = orderDetail.ProductId, UnitPrice = orderDetail.UnitPrice, Quanity = orderDetail.quantity, Discount = orderDetail.Discount });
}
AutoMapper alternative projection
Install AutoMapper, run the following from the package manager console:
Install-Package AutoMapper
Create an AutoMapperConfig.cs in the App_Start folder with the mappings, similar to below:
public static class AutoMapperConfig
{
public static void Configure()
{
Mapper.CreateMap<OrderDetails, OrderDetailViewModel>();
}
}
In your global asax call the configure method:
protected void Application_Start()
{
...
AutoMapperConfig.Configure();
...
}
Then map in your controller:
var orderDetailsViewModel = new OrderDetailsViewModel();
orderDetailsViewModel.OrderDetails = Mapper.Map<List<OrderDetails>, List<OrderDetailsViewModel>>(orderDetails);
I prefer to use the AutoMapper approach as the mapping is defined globally and can be reused within your app.
Returning your view model
Your view model would then be passed back as follows:
return View(orderDetailsViewModel);
Razor output
You access it in your view by adding a model reference at the top:
#model OrderDetailsViewModel
Then output the properties as follows, I've only included OrderId but you can just add the fields the same way:
<table>
<tr>
<th>OrderId</th>
</tr>
#foreach(var orderDetail in Model.OrderDetails)
{
<tr>
<td>#orderDetail.OrderId</td>
</tr>
}
</table>
You have create ViewModel for that.
For example in your model folder create a class:
public class MyViewModel // Whatever name you want to give
{
//My fields which I want to pass to View
publis string Field1{get;set;}
etc
etc
}
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
List<MyViewModel> viewModelList = new List<MyViewModel>();
foreach(var orderDetail in orderDetails)
{
MyViewModel viewModel = new MyViewModel(); //Create an object of your ViewModel
viewModel.Field1 = orderDetails.Field1; //set all feilds like that
viewModelList.Add(viewModel);
}
return View(viewModelList); // Pass View Model to View
}
Note: You have to create View for your ViewModel
Like
#model `List<MyViewModel>`
then use this ViewModel to access properties.
To know more about what is ViewModel, refer to the link below:
http://sampathloku.blogspot.ae/2012/10/how-to-use-viewmodel-with-aspnet-mvc.html
in the Controller class write :
public ActionResult Index()
{
DataRerieveClient _proxy = new DataRerieveClient();
var orderDetails = _proxy.GetProductDetails(null);
return View(orderDetails);
}
i assume your project name is MvcApplication2 and your class name is in Model Folder. so add follow code in top of View (sample.cshtml) :
#model MvcApplication2.Models.OrderDetail
ok , you can use this code to access properties of DataRecieveClient :
<div class="display-label">
#Html.DisplayNameFor(model => model.F1)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.F1)
</div>
Sorry for poor english.!

Categories

Resources