Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

MVC question, 2 models in 1 view...

Options
  • 11-03-2015 1:55pm
    #1
    Closed Accounts Posts: 1,143 ✭✭✭


    Hi folks,

    Just a quick question, I have been learning to use MVC, I previously developed using Webforms so MVC is new to me. I've asked a few questions on the forum previously to help get me started with displaying data, from a DB, etc.

    I have this now working fine using a DBContext and my MS2012 SQL DB. I can read info from my DB and save info to my DB.

    Last night I decided to expand a bit upon what I am doing and I now want to read and/or edit data from two different tables (using 2 different models), from the same view, say for example, one model named 'Vehicle' and another model named 'Product'.

    On the face of it this is easy to do, after a bit of Googling, I added in a new model to my project as follows:

    [HTML]
    namespace MyMVCSolution.Models
    {

    public class MyMergedModel
    {

    //public MyMVCSolution.Models.Vehicle Vehicle { get; set; }
    //public MyMVCSolution.Models.Product Product { get; set; }
    public IEnumerable<MyMVCSolution.Models.Vehicle> Vehicles { get; set; }
    public IEnumerable<MyMVCSolution.Models.Product> Products { get; set; }

    }

    public class MyMergedModelDBContext : DbContext
    {
    public DbSet<MyMVCSolution.Models.Vehicle> VehicleDBs { get; set; }
    public DbSet<MyMVCSolution.Models.Product> ProductDBs { get; set; }

    }


    }
    [/HTML]My View looks like this:

    [HTML]
    @model IEnumerable<MyMVCSolution.Models.MyMergedViewModel>
    @{
    ViewBag.Title = "View My Queries";
    Layout = "~/Views/Shared/_Layout.MobileThemeroller.cshtml";
    }


    @using (Html.BeginForm("UpdateQuery", "Home", FormMethod.Post))
    {
    <div ID="MyCollapsibleSet" data-role="collapsible-set" style="box-shadow:none;" data-iconshadow="false">
    @foreach (var item in Model) {


    @Html.DisplayFor(modelItem => item.Vehicle.VehicleID)<br /></div>@Html.DisplayFor(modelItem => item.Vehicle.VehicleMake) @Html.DisplayFor(modelItem => item.Vehicle.VehicleModel)<br />@Html.DisplayFor(modelItem => item.Vehicle.PaymentStatus)</h3>
    <ul data-role="listview" id="MyListView" data-inset="false" data-theme="d">

    <li><b>TID: </b>@Html.DisplayFor(modelItem => item.Vehicle.ID)<li>
    <li><b>Created: </b>@Html.DisplayFor(modelItem => item.Timestamp)</li>
    <li><b>Make: </b>@Html.DisplayFor(modelItem => item.Vehicle.VehicleMake)</li>
    <li><b>Model: </b>@Html.DisplayFor(modelItem => item.Vehicle.VehicleModel)</li>
    [/HTML](Intellisense is showing a red line under every instance of 'Vehicle' above...)

    My Controller:

    [HTML]
    var context = new MyMergedModelDBContext();

    var query = context.MyMergedModelDBContext.Where(p => p.Status == QueryStatus);

    if (!string.IsNullOrEmpty(QueryStatus))
    {
    //query = query.Where(p => p.Status == QueryStatus);
    query = query.OrderByDescending(p => p.ID);
    }

    var results = query.ToList(); //this executes your query and retrieves the results into memory

    return View(results);

    [/HTML]Basically I'm just trying to expand upon the solution that was advised to me in this thread below, which has been working fine, to adapt it to use 2 models in the same view, as I am now dealing with data coming from 2 different tables accessed via 2 different models and DBContexts but I've obviously gotten something wrong here although it looks like it should be an easy thing to do.

    Thanks a mil in advance for any help with this...

    http://www.boards.ie/vbulletin/showthread.php?t=2057380052


«1

Comments

  • Registered Users Posts: 403 ✭✭counterpointaud


    It's been a while since I have been working with MVC, but I don't think you need DbSet definitions for collections like that, or a seperate DbContext for the collections. Maybe let the DbContext only know about the model (singular), and compose your view model whatever way you like after that? I typically just use one DbContext in a simple app.

    EDIT: Looking at it again, I am not clear what you are doing. Maybe post your product and vehicle models for clarity, you may be fighting the ORM a bit here.


  • Registered Users Posts: 586 ✭✭✭Aswerty


    You are bumping into something that every MVC developer will have bumped into before. The solution, similar to what you have, is to create another model that can contain the data you want to pass to the view. This is typically called a View Model. It is common for every model passed to a view to be a View Model. This article explains different approaches to passing Domain Models and View Models to a view. Personally I don't think a Domain Model should ever be directly passed to a view – the data should always be mapped to a View Model first. I use AutoMapper for mapping Domain Models to View Models.

    In your solution the main thing that stands out for me is that the MyMergedModel class should not inherit from DbContext. This is because this model is not persisted to the database (i.e. there is no MyMergedModel table in the database schema). Instead you might just create a new folder and namespace called MyMVCSolution.ViewModels which the MyMergedModel class is placed in. Then you would seperately retrieve the Products and Vehicles from the database and assign them to the View Model.

    As an aside: in your code you use MyMergedViewModel in the View but you only created a class called MyMergedModel. Is this a typo or do you have another class?

    So you'd just have the following ViewModel:
    namespace MyMVCSolution.ViewModels
    {
    
        public class MyMergedModel
        {
            public IEnumerable<MyMVCSolution.Models.Vehicle> Vehicles { get; set; }
            public IEnumerable<MyMVCSolution.Models.Product> Products { get; set; }
    
        }
    }
    

    And at the top of your View:
    @model MyMVCSolution.ViewModels.MyMergedModel
    
    // you could access data with the following
    @foreach (var vehicle in Model.Vehicles) {
    
    }
    
    @foreach (var product in Model.Products) {
    
    }
    

    And the controller might look like:
    var vehicles = context.Vehicles.Where(v => v.Something == somethingElse).AsEnumerable<Vehicle>();
    var products = context.Products.Where(p => p.Something == somethingElse).AsEnumerable<Vehicle>();
    
    var model = new MyMergedModel
    {
        Vehicles = vehicles,
        Products = products
    };
    
    return View(model);
    

    The code would be a little different if the Vehicles and Products were related insted of being two independent enumerables. So if that is the case you might indicate so.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Sorry that was a typo, there is just one new model called MyMergedModel, I'm just digesting the advice from the 2 posters above and seeing what changes I need to make to give this another shot, thanks a mil for the advice to the two posters above.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    The code would be a little different if the Vehicles and Products were related insted of being two independent enumerables. So if that is the case you might indicate so.

    Vehicles & Products are not related, two separate models just to clarify that. I think I'm doing something wrong with my DBContext class in my model:

    Basically the problem I'm having now is that when I try to use:

    [HTML]
    @model IEnumerable<MyMVCSolution.Models.MyMergedModel>

    @using (Html.BeginForm("UpdateQuery", "Home", FormMethod.Post))
    {
    <div ID="MyCollapsibleSet" data-role="collapsible-set" style="box-shadow:none;" data-iconshadow="false">
    @foreach (var Vehicle in Model.Vehicles) {
    [/HTML]I'm getting an intellisense error at Model.Vehicles in the code directly above (red quiggle is just under "Vehicles"), saying:

    "System.Collection.Generic.IEnumerable<MyMVCSolution.Models.MyMergedModel> does not contain a definition for 'Vehicles' and no extension method '"Vehicles' accepting a first argument of type "System.Collection.Generic.IEnumerable<MyMVCSolution.Models.MyMergedModel>" could be found (are you missing a using directive or an assembly reference?)

    This is my model code:

    [HTML]
    using System;
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Configuration;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Collections;
    using System.ComponentModel;
    using System.Text;
    using System.Net;
    using System.IO;
    using System.Xml;
    using System.Xml.Linq;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using System.Web.Mvc;

    namespace MyMVCSolution.Models
    {

    public class MyMergedModel
    {



    public IEnumerable<MyMVCSolution.Models.Vehicle> Vehicles { get; set; }
    public IEnumerable<MyMVCSolution.Models.Product> Products { get; set; }

    }

    public class MyMergedModelDBContext : DbContext
    {
    public DbSet<MyMVCSolution.Models.Vehicle> VehicleDBs { get; set; }
    public DbSet<MyMVCSolution.Models.Product> ProductDBs { get; set; }

    }


    }
    [/HTML]My controller code, based on the advice given on thread is now:
    [HTML]
    string QueryStatus = "ProductIsInStock";
    string StockID = "ProductID1";
    var context = new MyMergedModelDBContext();

    var vehicles = context.VehicleDBs.Where(v => v.Status == QueryStatus).AsEnumerable<Vehicle>();
    var products = context.ProductDBs.Where(p => p.StockID == StockID).AsEnumerable<Product>();

    var model = new MyMergedModel
    {
    Vehicles = vehicles,
    Products = products
    };

    return View(model);

    [/HTML]My controller is not raising any errors, intellisense can find the variables in my Vehicle & Product models (highlighted in green above), but my view is not hooking up in the same way for some reason I can't work out and intellisense cannot find the two models and the variables defined within the models (obviously because it can't find the respective model, which is Vehicle and Product, within MyMergedModel).


  • Registered Users Posts: 403 ✭✭counterpointaud


    Shouldn't
    @model IEnumerable<MyMVCSolution.Models.MyMergedModel>
    

    just be:
    @model MyMVCSolution.Models.MyMergedModel
    

    Why do you need an IEnumberable of MyMergedModel ?

    Also, your DbContext should typically be composed of all classes which are models of db tables, it seems like you may be making a seperate DbContext for one ViewModel.


  • Advertisement
  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Shouldn't
    @model IEnumerable<MyMVCSolution.Models.MyMergedModel>
    
    just be:
    @model MyMVCSolution.Models.MyMergedModel
    
    Why do you need an IEnumberable of MyMergedModel ?

    Also, your DbContext should typically be composed of all classes which are models of db tables, it seems like you may be making a seperate DbContext for one ViewModel.

    I'm afraid I'm not up to speed enough with MVC to know the difference between what you suggested above, I was advised to do this (to use @Model IEnumerable on the previous thread I mentioned in my OP), when I was using a single model to display several rows of data from one particular table in my DB, and this worked out fine for me so I didn't really want to change it as it was working for me and I didn't see anything new when trying to use 2 models in the one view that needed me to depart from what had previously worked for me when I was just using one model in my view.

    EDIT: I thought (and I'm probably wrong here!), but I thought that where I previously had one model with one DBContext, that where I made a new model that encapsulted 2 other models, that this new "supermodel" for want of a better word lol, would need its own DBContext?


  • Registered Users Posts: 403 ✭✭counterpointaud


    Let's break down what is happening:

    -You are defining a ViewModel which contains two collections, one for Vehicle types, one for Product types

    -You are populating both of these collections in your controller and passing the container (ViewModel) to your view

    -You are then telling your View that you are, in fact, expecting a collection of the ViewModel defined, so a collection of collections, if you like.


  • Registered Users Posts: 403 ✭✭counterpointaud


    EDIT: I thought (and I'm probably wrong here!), but I thought that where I previously had one model with one DBContext, that where I made a new model that encapsulted 2 other models, that this new "supermodel" for want of a better word lol, would need its own DBContext?

    I am almost sure this is not correct, one DbContext will suffice for most situations.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Let's break down what is happening:

    -You are defining a ViewModel which contains two collections, one for Vehicle types, one for Product types

    -You are populating both of these collections in your controller and passing the container (ViewModel) to your view

    -You are then telling your View that you are, in fact, expecting a collection of the ViewModel defined, so a collection of collections, if you like.

    So basically I don't need a DBContext at all in my MergedModel because I have already got 2 collections in that new containing model, am I right there?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    EDIT: I thought (and I'm probably wrong here!), but I thought that where I previously had one model with one DBContext, that where I made a new model that encapsulted 2 other models, that this new "supermodel" for want of a better word lol, would need its own DBContext?

    DbContext is just something that is part of Entity Framework. It doesn't have any relationship with MVC. Once you can get your Product and Vehicle data out of the database this data can be contained in any normal class that has no relationship with DbContext.

    If in your database there was a table called MyMergedModel which had relationships with the Vehicles and Products tables then yes MyMergedModel would derive from DbContext because it would then have "Context" within the "DataBase". It's a very literal class name!
    So basically I don't need a DBContext at all in my MergedModel because I have already got 2 collections in that new containing model, am I right there?

    Yes you are right there.


  • Advertisement
  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »

    Yes you are right there.

    Last question to get this finally sorted then is should I access the data from my controller, as at the mo I'm using a DBContext that I carried over from the solution I used previously on the forum when I just had a single model in my view, (it worked so I was reluctant to go making changes to the solution given that I'm still not very proficient with MVC!)...

    [HTML]
    string QueryStatus = "ProductIsInStock";
    string StockID = "ProductID1";
    var context = new MyMergedModelDBContext();

    var vehicles = context.VehicleDBs.Where(v => v.Status == QueryStatus).AsEnumerable<Vehicle>();

    var products = context.ProductDBs.Where(p => p.StockID == StockID).AsEnumerable<Product>();

    var model = new MyMergedModel
    {
    Vehicles = vehicles,
    Products = products
    };
    return View(model);
    [/HTML]


  • Registered Users Posts: 586 ✭✭✭Aswerty


    On rereading; one of the things I was telling you not to do you weren't even doing. Your approach to DbContext was fine from the get go. The naming and architecture is just a tad confusing.

    But yeah it's fine calling to the database from your controller. Some people would tell you to push it into a separate class for architectural reasons but doing it in the controller is "technically" fine.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    On rereading; one of the things I was telling you not to do you weren't even doing. Your approach to DbContext was fine from the get go. The naming and architecture is just a tad confusing.

    But yeah it's fine calling to the database from your controller. Some people would tell you to push it into a separate class for architectural reasons but doing it in the controller is "technically" fine.

    My prob now is that the only way I know to access the DB from the controller is by using a DBContext. But a poster above has advised me that I don't need it in this case and should not really be using it...


  • Registered Users Posts: 586 ✭✭✭Aswerty


    My prob now is that the only way I know to access the DB from the controller is by using a DBContext. But a poster above has advised me that I don't need it in this case and should not really be using it...

    Think of an instance of a DbContext as a database connection. You can open a single database connection and use the same one all the time. This isn't a great idea though because in web applications it would mean you keep a single connection open for weeks at a time; this can result in performance issues. Also DbContext is not thread safe. In MVC every HTTP request is handled in a separate thread so you don't want multiple threads, during simultaneous requests, accessing the same DbContext.

    For simple single threaded desktop applications you can get away with a single DbContext.

    What you are doing at the moment is fine. There is things you could do better but that's going off topic quite a bit I think.

    Edit:

    Just to add couterpointaud might have meant one class that derives from DbContext is enough (i.e. MyMergedModelDBContext). Not that a single instance of said class is enough.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    Think of an instance of a DbContext as a database connection. You can open a single database connection and use the same one all the time. This isn't a great idea though because in web applications it would mean you keep a single connection open for weeks at a time; this can result in performance issues. Also DbContext is not thread safe. In MVC every HTTP request is handled in a separate thread so you don't want multiple threads, during simultaneous requests, accessing the same DbContext.

    For simple single threaded desktop applications you can get away with a single DbContext.

    What you are doing at the moment is fine. There is things you could do better but that's going off topic quite a bit I think.

    Edit:

    Just to add couterpointaud might have meant one class that derives from DbContext is enough (i.e. MyMergedModelDBContext). Not that a single instance of said class is enough.

    So is this correct do you think?

    [HTML]
    namespace MyMVCSolution.Models { public class MyMergedModel { //public MyMVCSolution.Models.Vehicle Vehicle { get; set; } //public MyMVCSolution.Models.Product Product { get; set; } public IEnumerable<MyMVCSolution.Models.Vehicle> Vehicles { get; set; } public IEnumerable<MyMVCSolution.Models.Product> Products { get; set; } } public class MyMergedModelDBContext : DbContext { public DbSet<MyMVCSolution.Models.Vehicle> VehicleDBs { get; set; } public DbSet<MyMVCSolution.Models.Product> ProductDBs { get; set; } } }
    [/HTML]

    My problem here is that this code above is letting me access my DB columns (via the above model) in my controller, but my view is not letting me type access the same columns when I try to use:

    @foreach (var Vehicle in Model.Vehicles) {

    Even though I am using @Model IEnumerable <MyMVCSolution.Models.MyMergedView>

    And you can see MyMergedModel above, but there is an intellisense error under 'Vehicles' where I try to use: @foreach (var Vehicle in Model.Vehicles) {


    :confused::confused::confused:


  • Registered Users Posts: 586 ✭✭✭Aswerty


    It is very obvious whats going on there. Both me and the other poster have tried to highlight it.

    If you can answer the following question you should begin to understand.

    What are you passing to the View and what data structure does the View expect?

    Because I can tell you that what is being passed and what is expected is not the same. A tip: get rid of the var keyword in your controller and replace it with the actual types. It should be more obvious what the problem is.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    It is very obvious whats going on there. Both me and the other poster have tried to highlight it.

    If you can answer the following question you should begin to understand.

    What are you passing to the View and what data structure does the View expect?

    Because I can tell you that what is being passed and what is expected is not the same. A tip: get rid of the var keyword in your controller and replace it with the actual types. It should be more obvious what the problem is.

    I've used 'var' 3 times, should I be using 'model' or 'DBContext'?

    As far as I'm seeing, I'm trying to pass a model to my view via my controller? Or to take a longer view of it as I see it, I'm trying to use a DBContext, which in my head is an instance of the specific DB table I am trying to work with, to populate my model with data (which is several records of data in my DB), and then display this data in my view?


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Ok I think I'm slowly getting it now:

    MyMergedModelDBContext context = new MyMergedModelDBContext();

    for a start!


  • Registered Users Posts: 403 ✭✭counterpointaud


    I've used 'var' 3 times, should I be using 'model' or 'DBContext'?

    As far as I'm seeing, I'm trying to pass a model to my view via my controller? Or to take a longer view of it as I see it, I'm trying to use a DBContext, which in my head is an instance of the specific DB table I am trying to work with, to populate my model with data (which is several records of data in my DB), and then display this data in my view?


    DbContext should not be thought of as representing a table, rather as representing a database, or set of tables.

    Aswerty is correct, earlier I was trying to suggest that you should just have one class deriving from DbContext, not one instance, or one per table / model.

    The main issue though, is the difference between what you are returning from your controller action and what the view is expecting.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    DbContext should not be thought of as representing a table, rather as representing a database, or set of tables.

    Aswerty is correct, earlier I was trying to suggest that you should just have one class deriving from DbContext, not one instance, or one per table / model.

    The main issue though, is the difference between what you are returning from your controller action and what the view is expecting.

    I'm really confused here. Earlier the advice was that I didn't need a DBContext in my MergedModel because I already had 2 collections set up in there, and to have a DBContext was saying I was trying to code for a set up where I had "collections of collections" (I'm calling these 2 collections my 2 child models, 'Vehicle' and 'Product' respectively...

    But now it seems I do need a DBContext, I thought I needed to get rid of my DBContext and just access the model from my controller, I'm really lost here to be honest, I've googled the absolute shít out of this problem and can't figure out why my solution isn't letting me use:

    @foreach (var Vehicle in Model.Vehicles) {}

    or

    @foreach (var Product in Model.Products) {}

    I'll have to be honest here lads, I'm not proficient enough with MVC to get the hints with where I'm going wrong here, I do obviously want to learn where I am fúcking up but I've googled the shít out of this before I asked for help on the forum and as far as I could see, this was a slight change to a solution I got help with before that has previously worked, so I can't work out where I'm going wrong here.


  • Advertisement
  • Registered Users Posts: 403 ✭✭counterpointaud


    I'm really confused here. Earlier the advice was that I didn't need a DBContext in my MergedModel because I already had 2 collections set up in there, and to have a DBContext was saying I was trying to code for a set up where I had "collections of collections" (I'm calling these 2 collections my 2 child models, 'Vehicle' and 'Product' respectively...

    But now it seems I do need a DBContext, I thought I needed to get rid of my DBContext and just access the model from my controller, I'm really lost here to be honest, I've googled the absolute shít out of this problem and can't figure out why my solution isn't letting me use:

    @foreach (var Vehicle in Model.Vehicles) {}

    or

    @foreach (var Product in Model.Products) {}

    I'll have to be honest here lads, I'm not proficient enough with MVC to get the hints with where I'm going wrong here, I do obviously want to learn where I am fúcking up but I've googled the shít out of this before I asked for help on the forum and as far as I could see, this was a slight change to a solution I got help with before that has previously worked, so I can't work out where I'm going wrong here.

    You need a DbContext in order to use Entity Framework to map database tables to model objects. Your model objects in this case are Vehicle and Product. You just need one DbContext in your app, which has DbSet properties for each model (table representation) you need to access.

    The reason you can't use model.Vehicles, is because as far as your view is concerned, your model does not contain a collection of vehicles. It contains an collection of MyMergedViewModel objects, which each contain a collection of vehicles and a collection of products.

    Have you tried changing the model declaration in the view to just MyMergedViewModel as I suggested ?


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    You need a DbContext in order to use Entity Framework to map database tables to model objects. Your model objects in this case are Vehicle and Product. You just need one DbContext in your app, which has DbSet properties for each model (table representation) you need to access.

    The reason you can't use model.Vehicles, is because as far as your view is concerned, your model does not contain a collection of vehicles. It contains an collection of MyMergedViewModel objects, which each contain a collection of vehicles and a collection of products.

    Have you tried changing the model declaration in the view to just MyMergedViewModel as I suggested ?

    Just trying this now, have to clear 24 errors first, I've completely lost the bit of a handle I previously had on this...


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    You need a DbContext in order to use Entity Framework to map database tables to model objects. Your model objects in this case are Vehicle and Product. You just need one DbContext in your app, which has DbSet properties for each model (table representation) you need to access.

    The reason you can't use model.Vehicles, is because as far as your view is concerned, your model does not contain a collection of vehicles. It contains an collection of MyMergedViewModel objects, which each contain a collection of vehicles and a collection of products.

    Have you tried changing the model declaration in the view to just MyMergedViewModel as I suggested ?

    I've tried using just MyMergedView instead but it still won't work. What I don't get is, in relation to what I've highlighted in bold above, I am returning a collection of MyMergedView model objects, of which there are 2, one being 'Vehicles' and one being 'Products'.

    So why can't I tell my View to go into whichever one of those objects I want to use, say for example 'Vehicles', when I use the code below???

    @foreach (var Vehicle in Model.Vehicles) {} ???

    Is this not what I am trying to do, am I not using the statement above to tell my view that I want to use the object 'Vehicles' and that I want to access the data in that object (data that is essentially mapped from my DB table???)


  • Registered Users Posts: 586 ✭✭✭Aswerty


    This actually doesn't have anything to do with MVC. I think you're misunderstanding how Collections work. Your controller is passing a single instance of the class MyMergedModel to the View. Your View expects an IEnumerable<MyMergedModel>.

    Just to help you understand (this isn't a solution), try:
    //changing this
    @foreach (var Product in Model.Products) {}
    
    //to this
    @foreach (var Product in Model.First().Products) {}
    

    This would cause the View to be correct but wouldn't solve the mismatch of the type being passed from the controller to the View. What would make the most sense is to change the model expected in the View.
    //from this
    @model IEnumerable<MyMergedModel>
    
    //to this
    @model MyMergedModel
    

    In this manner you can access the Enumerables in the MyMergedModel in the following way:
    @foreach (var Product in Model.Products) {}
    

    As far as I can see your controller is fine and your DbContext stuff is fine. Like counterpointaud states you are using an Enumerable that contains Enumerables and treating it like it is just one layer of Enumerables. This is the same as trying to use an array of arrays like it's just a basic array.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    This actually doesn't have anything to do with MVC. I think you're misunderstanding how Collections work. Your controller is passing a single instance of the class MyMergedModel to the View. Your View expects an IEnumerable<MyMergedModel>.

    Just to help you understand (this isn't a solution), try:
    //changing this
    @foreach (var Product in Model.Products) {}
    
    //to this
    @foreach (var Product in Model.First().Products) {}
    
    This would cause the View to be correct but wouldn't solve the mismatch of the type being passed from the controller to the View. What would make the most sense is to change the model expected in the View.
    //from this
    @model IEnumerable<MyMergedModel>
    
    //to this
    @model MyMergedModel
    
    In this manner you can access the Enumerables in the MyMergedModel in the following way:
    @foreach (var Product in Model.Products) {}
    
    As far as I can see your controller is fine and your DbContext stuff is fine. Like counterpointaud states you are using an Enumerable that contains Enumerables and treating it like it is just one layer of Enumerables. This is the same as trying to use an array of arrays like it's just a basic array.

    I've tried everything you've suggested above at least 5 times now and it isn't working here for me. You've suggested I do this:
    //changing this
    [U][B][SIZE=4]@foreach (var Product in Model.Products) {}[/SIZE][/B][/U]
    
    //to this
    @foreach (var Product in Model.First().Products) {}
    
    This would cause the View to be correct but wouldn't solve the mismatch of the type being passed from the controller to the View. What would make the most sense is to change the model expected in the View.

    [code]

    My problem is that ^^^ will not work for me! I've taken out the IEnumerable at the top of my view, I've tried this several times now and it still won't work as you've suggested...


  • Registered Users Posts: 586 ✭✭✭Aswerty


    I guess I've lost track of the changes that you've made so far.

    Have you tried throwing in a break point on:
    return View(model);
    

    and verified that the model contains the expected data and is not just null. Because if it is null that would bugger things up.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    This is the thing about MVC or EF or whatever it is I'm trying to work with here, it's hard to tell whether it is MVC or EF you are working with here. You google something you want to try and you find an answer and it says it's just 2 simple lines of code to work with 2 models in the same view and sure it's so easy, just continue along as you were.

    If I was still using webforms I'd just use 2 separate SQL connection strings and wire up my controls and I'd be sorted, there would be none of this crap where 3 days later, after just trying to take data from 2 different sources and stick them on a page/view you find yourself hopelessly bogged down in complex architectural considerations!

    //rant over!


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    I'm gonna post my latest code fresh here again:

    Before I do that, I just want to mention that now I can't use a foreach loop in my view because since I've taken out the

    @Model IENumerable<MYMVCSolution.models.MyMergedView>

    I am now getting an intellisense error under the word 'foreach' saying:

    forech statement cannot operate on variables on type MyMVCSolution.models.MyMergedView' because 'MyMVCSolution.models.MyMergedView' does not contain a public definition for 'GetEnumerator'


  • Registered Users Posts: 403 ✭✭counterpointaud


    I'm gonna post my latest code fresh here again:

    Before I do that, I just want to mention that now I can't use a foreach loop in my view because since I've taken out the

    @Model IENumerable<MYMVCSolution.models.MyMergedView>

    I am now getting an intellisense error under the word 'foreach' saying:

    forech statement cannot operate on variables on type MyMVCSolution.models.MyMergedView' because 'MyMVCSolution.models.MyMergedView' does not contain a public definition for 'GetEnumerator'

    I guess you are trying to iterate over Model, instead of Model.Products or Model.Vehicles ?


  • Advertisement
  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    I think I have it sorted now lads, will have to take this home with me and get a bit of grub and then crank laptop back up and test the code, it's looking good now, I can finally use: @foreach(item in model.vehicles) {}

    This I wasn't able to do so far, I'll go get a bite and come back at this with a better fresher attitude after that!

    Huge thanks to the both of you for your advice with this, not to mention your patience!


Advertisement