0

Ok so this is a follow-up from MVC 5 ASP.NET Entity Framework Collect Form Data through Range Input , My Database Structure Consists of a Survey Having Many Categories, A Category having many Questions, then a Question having many QuestionResults and finally QuestionResults having many CategoryResults, in the HomeController I have the models being bound through the ViewModel, but I now require it to be populated with my entities through the context with Linq, any help will be greatly appreciated.

I need to populate this ViewModel, which was created with the help of a very valuable stack-overflow contributor, with my Entities, all code is as below:

Main question: How can I bring in my entities into my SurveyVM ViewModel instance?

ViewModel

namespace MyApp
{
    public class SurveyVM
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<CategoryVM> Categories { get; set; }
    }

    public class CategoryVM
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<QuestionVM> Questions { get; set; }
    }

    public class QuestionVM
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public int Score { get; set; }
    }

    public class QuestionResult
    {
        public int ID { get; set; }
        public int QuestionId { get; set; }
        public int QuestionScore { get; set; }
    }
}

Models Linked to Entities and Subsequent Database

public class Question
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string CreatedBy { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public virtual Category Category { get; set; }
        public int CategoryId { get; set; }
        public virtual ICollection<QuestionResult> QuestionResult { get; set; }
        public virtual ICollection<QuestionFeedback> QuestionFeedback { get; set; }
    }
public class QuestionResult
    {
        public int Id { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public int QuestionScore { get; set; }
        //navigation properties
        public virtual ApplicationUser User { get; set; }
        public ICollection<CategoryResult> CategoryResult { get; set; }
        public virtual Question Question { get; set; }
        public int QuestionId { get; set; }
    }
public class CategoryResult
    {
        public int Id { get; set; }
        public int CategoryScore {get;set;}
        //navigation properties
        public virtual QuestionResult QuestionResult { get; set; }
        public int QuestionResultId { get; set; }

    }
public class Category
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string CreatedBy { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public virtual Survey Survey { get; set; }
        public int SurveyId { get; set; }
        public virtual ICollection<Question> Question { get; set; }
        public virtual ICollection<CategoryFeedback> CategoryFeedback { get; set; }
    }

HomeController

public ActionResult IndexSurveyViewModel()
        {
            SurveyVM model = new SurveyVM()
            {
                ID = 1,
                Name = "Survey 1",
                Categories = new List<CategoryVM>()
                {
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category A", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 1, Title = "Question 1A", Score = 2
                            }, 
                                new QuestionVM()
                            {
                                ID = 2, Title = "Question 2A", Score = 4
                            }
                        }
                    },
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category B", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 3, Title = "Question 1B", Score = 3
                            }, 
                                new QuestionVM()
                            {
                                ID = 4, Title = "Question 2B", Score = 5
                            }
                        }
                    },
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category C", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 5, Title = "Question 1C", Score = 1
                            }, 
                                new QuestionVM()
                            {
                                ID = 6, Title = "Question 2C", Score = 3
                            }
                        }
                    }   
                }
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult IndexSurveyViewModel(SurveyVM model)
        {
            List<QuestionResult> results = new List<QuestionResult>();
            foreach (CategoryVM category in model.Categories)
            {
                foreach (QuestionVM question in category.Questions)
                {
                    results.Add(new QuestionResult()
                    {
                        Id = question.ID,
                        QuestionScore = question.Score
                    });

                }
            }
            return View(model);
        }

View

@model STRA.Models.SurveyVM
@{
    Layout = null;
}

<!DOCTYPE html>


<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My app</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
    <style>
        .category {
            display: none;
            margin-left: 20px;
            margin-top: 10px;
        }

            .category:first-of-type {
                display: block;
            }

                .category:first-of-type button:last-of-type {
                    display: none;
                }

            .category:last-of-type button:first-of-type {
                display: none;
            }

        .question {
            margin-left: 20px;
            margin-top: 10px;
        }

        .buttons {
            margin: 20px;
        }

        input[type="text"] {
            width: 20px;
        }

        .slider {
            display: inline-block;
            width: 200px;
            margin-left: 20px;
        }
    </style>
</head>


<body>
    @using (Html.BeginForm())
    {
        @Html.HiddenFor(m => m.ID)
        @Html.DisplayFor(m => m.Name)
        for (int i = 0; i < Model.Categories.Count; i++)
        {
            <div class="category">
                @Html.HiddenFor(m => m.Categories[i].ID)
                @Html.DisplayFor(m => m.Categories[i].Name)
                @for (int j = 0; j < Model.Categories[i].Questions.Count; j++)
                {
                    <div class="question">
                        @Html.HiddenFor(m => m.Categories[i].Questions[j].ID)
                        @Html.DisplayFor(m => m.Categories[i].Questions[j].Title)
                        @Html.TextBoxFor(m => m.Categories[i].Questions[j].Score)
                        <div class="slider"></div>
                    </div>
                }
                <div class="buttons">
                    <button type="button" class="next">Next</button>
                    <button type="button" class="previous">Previous</button>
                </div>
            </div>
        }
        <input type="submit" />
    }


    <!-- JS includes -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>

    <script type="text/javascript">

            $('.slider').each(function() {
                var v = $(this).closest('.question').find('input[type="text"]').val();
                $(this).slider({
                    value: v,
                    min: 1,
                    max: 5,
                    change: function (event, ui) {
                        $(this).closest('.question').find('input[type="text"]').val(ui.value);
                    }
                });
            });
            $('.next').click(function() {
                $(this).closest('.category').hide().next('.category').show();
            });
            $('.previous').click(function() {
                $(this).closest('.category').hide().prev('.category').show();
            });
    </script>
</body>
</html>

My Code so far:

var survey = from s in db.Surveys
                         from c in db.Categories
                         from q in db.Questions
                         where s.Id == c.SurveyId
                         where c.Id == q.CategoryId
                         select new SurveyVM
                         {
                             ID = s.Id,
                             Name = s.Title,
                             Categories = new List<CategoryVM>()
                             {
                                 new CategoryVM()
                                 {
                                     ID = c.Id,
                                     Name = c.Title,
                                     Questions = new List<QuestionVM>()
                                     {
                                         new QuestionVM()
                                         {
                                             ID = q.Id,
                                             Title = q.Title
                                         }
                                     }
                                 }
                             }
                         };

How can I bring in my entities into my SurveyVM ViewModel instance?

7
  • to be honest im not too sure how to approach it Commented Jun 4, 2015 at 6:41
  • Your basically asking us to write your code. What's the specific question? Narrow it down to what you need to know and only post code specific to the problem. Commented Jun 4, 2015 at 9:07
  • SOrry, I thought I would post the relevant classes, I am attempting to bind my entities to a linq statement and pass it into the view through a viewmodel, i will post my linq statements as above Commented Jun 4, 2015 at 9:12
  • Ok, how can I bring in my entities into my SurveyVM ViewModel instance? Commented Jun 4, 2015 at 9:37
  • @GertArnold Just because there's no specific question being asked doesn't mean that it is a Code Review question. As can be seen by the edit I made and the OP's comment above mine, this question does not belong on CR. Commented Jun 4, 2015 at 12:21

2 Answers 2

3

This might point you in the right direction, its using lambda expressions.

List<SurveyVM> surveys = DbContext.Survey.Select(s=> new SurveyVM {
    ID = s.ID,
    Name = s.Name,
    Categories = s.Category.Select(c => new CategoryVM {
        ID = c.ID,
        Name = c.Name,
        Questions = c.Question.Select(q=> new QuestionVM {
            ID = q.ID,
            Title = q.Title,
            Score = q.Score
        }).ToList()
    }).ToList()
}).SingleOrDefault();

This is off the top of my head as I dont have anything to test it with.

Also as a side note I would look at using EditorTemplates/DisplayTemplates instead of your loop in your view as it will make your code easier to read.

for (int i = 0; i < Model.Categories.Count; i++)
    {
        <div class="category">
            @Html.HiddenFor(m => m.Categories[i].ID)
            @Html.DisplayFor(m => m.Categories[i].Name)
            @for (int j = 0; j < Model.Categories[i].Questions.Count; j++)
            {
                <div class="question">
                    @Html.HiddenFor(m => m.Categories[i].Questions[j].ID)
                    @Html.DisplayFor(m => m.Categories[i].Questions[j].Title)
                    @Html.TextBoxFor(m => m.Categories[i].Questions[j].Score)
                    <div class="slider"></div>
                </div>
            }
            <div class="buttons">
                <button type="button" class="next">Next</button>
                <button type="button" class="previous">Previous</button>
            </div>
        </div>
    }
Sign up to request clarification or add additional context in comments.

Comments

1

When you have Domain models and each of domain model have a lot of view models then it is the right time to use Automapper. All documentation you can find here:

https://github.com/AutoMapper/AutoMapper/wiki/Getting-started

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.