Passing multiple models to view [duplicate] - c#

This question already has answers here:
The model item passed into the dictionary is of type .. but this dictionary requires a model item of type
(7 answers)
Closed 5 years ago.
I am developing an asp mvc 5 website. I have 3 models which are appointments, consultations and contacts. now i want to display all the details of these 3 models in a view called userdetails. What i have done so far
Created a view model
public class AllServices
{
public List<Contact> Contacts { get; set; }
public List<Appointment> Appointments { get; set; }
public List<Consultation> Consultations { get; set; }
}
Then created the controller action method
public ActionResult userdetails()
{
AllServices services = new AllServices();
services.Appointments = dbcontext.Appointments.ToList();
services.Consultations = dbcontext.Consultations.ToList();
services.Contacts = dbcontext.Contacts.ToList();
return View(services);
}
and in view i made
#model List<Astrology.ViewModels.AllServices>
....
#foreach(var item in Model)
{
#item.Appointments
}
but when i run the page iam getting an error like this
The model item passed into the dictionary is of type 'Astrology.ViewModels.AllServices', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[Astrology.ViewModels.AllServices]'.
Can someone please help me with it. Iam stuck with this.

The error is telling you that you're only passing a single AllServices model when it expects a List of AllServices models. You need to either change the view to expect one model or put the single model into a list.
EDIT (adding code sample)
Change your Controller to something like this:
public ActionResult userdetails()
{
List<AllServices> lservices = new List<AllServices>();
AllServices services = new AllServices();
services.Appointments = dbcontext.Appointments.ToList();
services.Consultations = dbcontext.Consultations.ToList();
services.Contacts = dbcontext.Contacts.ToList();
lservices.Add(services);
return View(lservices);
}

Related

'Object reference not set' error, but list has 27 references in C# .Net [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 10 months ago.
I'm using Visual Studio 2019 and I'm getting this error when I'm trying to populate a list. My coworker tried to help me and thought it was strange to get the following error since my list has 27 references to objects, so part of it is being recognized but part of it isn't:
An unhandled exception occurred while processing the request. NullReferenceException: Object reference not set to an instance of an object.
Here is some of the models:
public class BogusModel
{
public List<County> Counties { get; set; }
public SelectList CountySelectList { get; set; }
}
Here is where the class for it is in the model:
public class County
{
public string CountyName { get; set; }
public double CountyRate { get; set; }
public County(string CountyName, double CountyRate)
{
this.CountyName = CountyName;
this.CountyRate = CountyRate;
}
public County()
{
}
}
Here is the beginning of the method where I try to populate the list in the model:
public void createAndPopulateCounties()
{
Counties.Add(new County(CountyName = "Allegany", CountyRate = 0.0305));
}
And the controller where the method is called (I commented out the select list since that doesn't work either):
[HttpGet]
public IActionResult Index()
{
BogusModel model = new BogusViewModel();
// Call the method to create and populate the list of counties
model.createAndPopulateCounties();
// model.CountySelectList = new SelectList(model.Counties, "CountyName", "CountyName");
return View("Index", model);
}
My coworker and I tried changing the code in the County class that said this.CountyName = CountyName; a few different ways, I used to have code like this in my function
List<County> Counties = new List<County>();
but that was a problem since it wasn't populating the original list, it was creating a second one (my coworker noticed that). I can't figure this out from the other stack overflow postings, and none of the other postings mention references to the object. I tried to upload an image of the references, but StackOverflow said it was forbidden. But it does reference the County objects I tried to add, but then I get the runtime error.
Since you aren't passing any arguments to the constructor for your model, you could try initializing the list when you initialize the model like:
WithholdingViewModel model = new WithholdingViewModel{
Counties = new List<County>()
};
or, if you have a list of County object already, can do:
List<County> myCountyListFromEarlier = someMethodToBuildTheList();
WithholdingViewModel model = new WithholdingViewModel{
Counties = myCountyListFromEarlier
};

Pass Custom View Object from Controller to View

I have a simple problem. In my controller I take join of two tables and return like this:
data = ...
select new { Contacts = item, Applications = items, Answers = j }
This is working fine. I am getting what I want: e.g. 62 data objects with the attribues I want.
But in the view how do I access these set of data points?
simple #model dynamic is not working? There must be some way to do this.
The best way to do that is by creating a ViewModel which will contain all the attributes that you need to display in your view.
public class DataViewModel {
public Contacts {get;set}
public Application {get;set;}
public Answers {get;set;}
}
Create a list of your "DataViewModel"
List<DataViewModel> Datas = new List<DataViewModel>();
After doing that, you will have to assign the values of each element in your controller after getting them from your "data" variable that you created by simply using a foreach loop.
foreach (var instance of data) {
// Assign those values here
}
You'll have to pass the list of your data (ViewModel) to your view from your controller like this :
return View(Datas);
and to call the list of your ViewModel in your view like this :
#model IEnumerable<models.DataViewModel>
Create an 'umbrella' model like:
public DataModel
{
public Contacts contacts {get;set}
public Application applications {get;set;}
public Answers answers {get;set;}
}
On controller:
select new DataModel(){ Contacts = item, Applications = items, Answers = j }
And have on View:
#model DataModel
Class
public DataModel
{
public Contacts {get;set}
public Application {get;set;}
public Answers {get;set;}
}
Controller
DataModel model = new DataModel();
model.Contacts = items;
model.Application = item;
model.Answers= items;
return View(model);
View
#model DataModel
// will get all three tables data here
#Model.Contacts
#Model.Application
#Model.Answers

Getting Model property of non-associated View object

When I am in the View of a specific object, I can acces all the instances by this loop in the View:
#foreach (Reservation r in Model) { }
But How to implement the same foreach cycle with Ski Class, which is not associated with this View?
Add whatever you need access to to your model. It is common to create specific ViewModel classes that are specific to one or a few views and provide access to whatever they need. In your case it would have Reservations as well as Ski data.
Example:
public class ReservationViewModel
{
public List<Reservation> Reservations { get; set; }
public List<Ski> Skis { get; set; }
}
Now in the View you can foreach over Model.Reservations, as well as over Model.Skis.

Domain Model Object to View Model Object in MVC

I want to use view model for displaying instead of domain model. I have got these view models classes:
public class ArticleDescriptionViewModel
{
public string Title { get; set; }
public DateTime DateCreated { get; set; }
}
public class HomePage
{
public List<ArticleDescriptionViewModel> Articles { get; set; }
}
In the domain model i have got:
public class ArticleDescription
{
public string Title { get; set; }
public DateTime DateCreated { get; set; }
}
And this service method:
public List<ArticleDescription> GetArticlesDescription()
{
var articleDescription= from a in _ctx.Articles
select new ArticleDescription
{ Title = a.Title, DateCreated = a.DateCreated };
return articleDescription.ToList();
}
in the controller i want to match my list inside of my view model class with the list returned by my domain model class.
public ActionResult Index()
{
HomePage HomePageInstance = new HomePage();
HomePageInstance.Articles = _repo.GetArticlesDescription();
return View(HomePageInstance);
}
I have got an error:
"Cannot implicitly convert type System.Collections.Generic.List (DBayonaCode.Domain.Services.Models.ArticleDescription)' to 'System.Collections.Generic.List(DBayonaCode.Models.ArticleDescriptionViewModel)'"
But these two classes are equivalent? I am doing something wrong. I appreciate your help?
ArticleDescription and ArticleDescriptionViewModel are two different types, so there's no implicit conversion between them. You need to map your Domain Model object to your View Model object, you can do that either manually or with a tool like AutoMapper.
You could write extension methods like these to do the mapping:
public static class Mappings
{
public static ArticleDescriptionViewModel ConvertToView(this ArticleDescription article)
{
// Mapping Code
// return new ArticleDescriptionViewModel { ... }
}
public static List<ArticleDescriptionViewModel> ConvertToViews(this List<ArticleDescription> articles)
{
List<ArticleDescriptionViewModel> articleViews = new List<ArticleDescriptionViewModel>();
foreach (ArticleDescription article in articles)
{
articleViews.Add(article.ConvertToView())
}
return articleViews;
}
}
While MVC default project template offer just one model folder, thus implicitly presenting the idea that models are one thing, in fact There are three types of data models potentially involved in an ASP.NET MVC application:
- Domain model objects will be passed from and to a middle tier services interfacing with databases.
- View Model objects are those that the Controller pass to the View.
- Input model objects are those that the default modelBinder or some custom modelBinder generates from the view, although in many cases the input models are the same view model objects.
Hope it helps.

How do I render a collection of objects with Nustache?

I'm attempting to use Nustache so that I can share rendering templates between back end and front end code in an ASP.Net web app. It's working fine when I just pass an object to a template, but I can't figure out how to get it to render a collection. So if I have a template like this:
{{#RenderItems}}
<th data-warning="{{WarningLevel}}" data-limit="{{LimitLevel}}">{{TotalHours}}</th>
{{/RenderItems}}
Then I want to pass in a collection of objects and get out a set of th elements.
Things I've tried:
Creating a class with the properties WarningLevel, LimitLevel and TotalHours, adding objects to a List and passing that directly: Nustache.Core.Render.FileToString(System.Web.HttpContext.Current.Server.MapPath("my.template"), ListOfObjects)
Doing the same thing, except creating an anonymous class: Nustache.Core.Render.FileToString(System.Web.HttpContext.Current.Server.MapPath("my.template"), new { RenderItems = ListOfObjects})
Instead of a list, using a Dictionary containing the same objects
Using a dictionary of dictionaries - so each item is itself a dictionary with the properties named above
The only way it renders anything at all is if I use an anonymous class, but I can't get it to populate the template with the named items whatever I do. I'm sure I'm missing something fairly obvious here, as I assume this should be straightforward, but the documentation says 'look in the code and the tests' but I can't work out which test is actually dealing with this scenario. Can someone either point me in the right direction, or provide some example code?
I was able to get this working with the following class and controller action:
public class Person {
public string Name { get; set; }
public string Email { get; set; }
}
public ActionResult Index() {
var people = new List<Person>() {
new Person { Name = "Albert Adams", Email = "albert#email.com" },
new Person { Name = "Bob Becker", Email = "bob#email.com" },
new Person { Name = "Charles Charles", Email = "charles#email.com" }
};
ViewData["People"] = people;
ViewResult viewResult = View();
viewResult.ViewEngineCollection = new ViewEngineCollection { new NustacheViewEngine() };
return viewResult;
}
And then Index.nustache:
{{#People}}
<p>{{Name}} - {{Email}}</p>
{{/People}}
Note that I pulled the latest changes from the Nustache repo this morning.

Categories