Question

I have a List of Recipes and each Recipe has a number of RecipeLines, I want to loop Each Recipe with it's corresponding Recipe Lines foreach Looping inside of the parent Recipe foreach.

Recipe Class

    namespace XXX.Models
    {
        public class Recipe
        {
            public int RecipeID { get; set; }
            public string RecipeName { get; set; }
            public string RecipeInstructions { get; set; }

            public virtual List<RecipeLine> RecipeLines { get; set; }
        }
    }

RecipeLine Class

    namespace XXX.Models
    {
        public class RecipeLine
        {
            public int RecipeLineID { get; set; }
            public float Quantity { get; set; }

            public int MeasurementID { get; set; }
            public int RecipeID { get; set; }
            public int IngredientID { get; set; }

            public virtual Measurement Measurement { get; set; }
            public virtual Recipe Recipe { get; set; }
            public virtual Ingredient Ingredient { get; set; }

        }
    }

No need to list the Ingredient and Measurement Class, but they are structured fine.

Now let's look at the ViewModel

    namespace XXX.ViewModels
    {
        public class RecipeLineViewModel
        {
            public IEnumerable<Recipe> Recipes { get; set; }
            public IEnumerable<RecipeLine> RecipeLines { get; set; }
        }
    }

And the PartialsController

    namespace XXX.Controllers
    {

        public class PartialsController : Controller
        {
            private XXXDb db = new XXXDb();

            public ActionResult RecipeList()
            {
                RecipeLineViewModel viewModel;

                viewModel = new RecipeLineViewModel();
                viewModel.Recipes = db.Recipes.ToList();
                viewModel.RecipeLines = db.RecipeLines.Include(r => 
                r.Measurement).Include(r => r.Ingredient);

                return PartialView("_RecipeList", viewModel);
            }
        }
    }

Now the partial view is Views > Partials > __RecipeList.cshtml

RecipeList Partial View

    @model XXX.ViewModels.RecipeLineViewModel

    @foreach (Recipe recipe in Model.Recipes) 
        {
        <div>@recipe.RecipeName</div>
        <div>@recipe.RecipeInstructions</div>

            foreach (RecipeLine recipeLines in Model.RecipeLines)
            {
                <div class="row">
                    <div class="large-12 columns">
                        @recipeLines.Quantity @recipeLines.Measurement.MeasurementEn 
                        @recipeLines.Ingredient.IngredientNameEn
                    </div>
                </div>
            }

        }
    }

(I printed the RecipeID at the end of each recipeLine to show that each recipe is repeating out Recipe Lines for RecipeID = 1 and not their Lines related to their own RecipeID. I'm a newbie to this stuff, I'm assuming that somewhere I should be telling the Recipe Lines about the RecipeID they should be looping for????

Here is the result I'm getting:

Parent/Child Loop Result:

Was it helpful?

Solution 2

Add a where Linq clause to foreach.

   @foreach (Recipe recipe in Model.Recipes) 
            {
            <div>@recipe.RecipeName</div>
            <div>@recipe.RecipeInstructions</div>

                foreach (RecipeLine recipeLines in Model.RecipeLines.Where(rl => rl.RecipeID == recipe.RecipeID))
                {

Upd:
Also you can definently include RecipeLine stuff in Recipes and you won't need RecipeLine Collection at all! Just loop through recipe.RecipeLines

Something like this:

viewModel.Recipes = db.Recipes.Include("RecipeLine").Include("RecipeLine.Measurement").
                .Include("RecipeLine.Ingredient");

OTHER TIPS

In your Recipie model you have have a List<RecipieLine> property which one would assume is to maintain one or more RecipieLine model objects. In your RecipieLineViewModel you have two separate IEnumerable collections exposing your Recipie and RecipieLine objects.

In your actual view, you are iterating over your Recipie collection:

@foreach (Recipe recipe in Model.Recipes)

Looks good, however, the following line is your issue:

foreach (RecipeLine recipeLines in Model.RecipeLines)

This enumerates over the RecipieLine model objects stored in your RecipieLineViewModel RecipieLine collection, however, it currently has no way of knowing which Recipie you are currently enumerating in your outer foreach.

You either want to provide a where LINQ clause of some sort using the data available to you from the current Recipie object enumeration, or alter the inner foreach to use the current Recipie enumeration rather than the Model.

Update

For completeness, here is an example of how to use the current Recipe object enumeration to access its associated RecipieLines:

@forech (var recipie in Model.Recipies)
{
    <div>@recipe.RecipeName</div>
    <div>@recipe.RecipeInstructions</div>
    foreach (var recipieLine in recipie.RecipieLines)
    {
        <div class="row">
            <div class="large-12 columns">
                // Do something with recipieLine here
            </div>
        </div>
    }
}

The above would be my preferred method as it is more efficient that performing a LINQ query each enumeration, and removes the IEnumerable<RecipieLine> from your ViewModel which is effectively duplicate code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top