Solved

MVC - Data-driven FAQs with nested Questions

Posted on 2013-11-30
8
219 Views
Last Modified: 2013-12-01
Hi:

I have an MVC app that uses bootstrap that creates accordion panels of questions that are driven from the database.  All works fine.  However, I'd like to be able to create data-driven sub-questions (1 level deep)  and am having difficulty.

I have a data repository that appears as follows:

 public class FaqsRepository : BaseRepository<Faq>, IFaqsRepository
    {
        public FaqsRepository(ScormLinkDbContext context)
            : base(context)
        {
        }


      
        public IEnumerable<FaqDto> GetFaqsSorted()
        {
            return DbSet.OrderBy(e => e.SortOrder)
                .Select(f => new FaqDto
                {
                    Id = f.Id,
                    Question =f.Question,
                    Answer=f.Answer,
                    SortOrder=f.SortOrder,
                    AnswerLink= "#" +  f.SortOrder ,
                    AnswerId = f.SortOrder 
                }
            
            );
        }

        public IEnumerable<FaqDto> GetSubFaqsSorted(int parentId)
        {
            return DbSet.OrderBy(e => e.SortOrder)
                .Where(e => e.ParentId == parentId)
                .Select(f => new FaqDto
                {
                    Id = f.Id,
                    Question = f.Question,
                    Answer = f.Answer,
                    SortOrder = f.SortOrder,
                    AnswerLink = "#" + f.SortOrder,
                    AnswerId = f.SortOrder
                }

            );
        }
    }

Open in new window


To initiate my view, I have the following:

public ActionResult Scorm()
        {
            var viewModel = new MyViewModel
            {
                FaqBriefs = _faqsRepository.GetFaqsSorted(),
                SubFaqDtos = _faqsRepository.GetSubFaqsSorted(0)
            };

            return View(viewModel);

        }

Open in new window


Finally, my view is as follows:

@model ScormLink.Models.MyViewModel


<div class="container pageWrap">
    <h2>SCORM - Asked and Answered</h2>
    <div id="accordion" class="panel-group">
        @foreach (var item in Model.FaqBriefs)
        {
            <div class="panel panel-info">
                <div class="panel-heading">
                    <div class="panel-title">
                        <a data-toggle="collapse" data-parent="#accordion" href=@Html.DisplayFor(modelItem => item.AnswerLink)>@Html.Raw(item.Question)</a>
                    </div>
                </div>
                <div id=@Html.DisplayFor(modelItem => item.AnswerId) class="panel-collapse collapse ">
                    <div class="panel-body">
                        @Html.Raw(item.Answer)

                        var myItem = item;
                        @foreach (var subItem in Model.SubFaqDtos(myItem.Id))
                        {
                            <div class="panel panel-info">
                                <div class="panel-heading">
                                    <div class="panel-title">
                                        <a data-toggle="collapse" data-parent="#accordion" href=@Html.DisplayFor(modelItem => subItem.AnswerLink)>@Html.Raw(subItem.Question)</a>
                                    </div>
                                </div>
                                <div id=@Html.DisplayFor(modelItem => subItem.AnswerId) class="panel-collapse collapse ">
                                    <div class="panel-body">
                                        @Html.Raw(item.Answer)
                                    </div>
                                </div>
                            </div>
                        }
                    </div>
                </div>
            </div>
        }
    </div>
</div>

Open in new window


Problem is, in the line:   @foreach (var subItem in Model.SubFaqDtos(myItem.Id)) in the View, I'm getting the error that a method, delegate or event is required.  I'm not sure how to handle this.  Any help greatly appreciated.

RBS
0
Comment
Question by:RBS
  • 4
  • 4
8 Comments
 
LVL 8

Expert Comment

by:Mohit Vijay
ID: 39687826
Hello

SubFaqDtos method should be your model, not in controller.
0
 

Author Comment

by:RBS
ID: 39688216
I'm sorry, I don't know what you mean.  I put it in MyViewModel from my controller just as I put FaqDtos in MyViewModel.
0
 
LVL 8

Expert Comment

by:Mohit Vijay
ID: 39688233
for Model I mean to say but SubFaqDtos in ScormLink.Models.MyViewModel, I think this is what you did.

Now its working?
0
 

Author Comment

by:RBS
ID: 39688278
I do not understand what you mean - could  you explain by changing the code you are talking about?
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 8

Expert Comment

by:Mohit Vijay
ID: 39688298
can you send me code for ScormLink.Models.MyViewModel and SubFaqDtos?
0
 

Author Comment

by:RBS
ID: 39688305
Sure:  

using System.Collections.Generic;
using ScormLink.Model;

namespace ScormLink.Models
{
    public class MyViewModel
    {
        public virtual IEnumerable<FaqDto> FaqBriefs { get; set; }

        public virtual IEnumerable<FaqDto> SubFaqDtos { get; set; }
    }
}

Open in new window

0
 
LVL 8

Accepted Solution

by:
Mohit Vijay earned 500 total points
ID: 39688313
So You are having SubFaqDtos as property, but in your view you are using it as method.

So You have to opt one of below changes

1
using System.Collections.Generic;
using ScormLink.Model;

namespace ScormLink.Models
{
    public class MyViewModel
    {
        public virtual IEnumerable<FaqDto> FaqBriefs { get; set; }

        public virtual IEnumerable<FaqDto> SubFaqDtos ()
{
//some code that return IEnumerable<FaqDto>
}
    }
}

Open in new window


2. in your view, you change that line as

@foreach (var subItem in Model.SubFaqDtos)
                        {

Open in new window

0
 

Author Closing Comment

by:RBS
ID: 39688336
Great - thanks! I didn't realize that ViewModels could include methods.  Here's the main change I made - and it works!

using System.Collections.Generic;
using ScormLink.Data;
using ScormLink.Model;

namespace ScormLink.Models
{
    public class SCORMViewModel
    {
        private readonly FaqsRepository _faqsRepository;
        private readonly ScormLinkDbContext _db = new ScormLinkDbContext();

        public SCORMViewModel()
        {
            _faqsRepository = new FaqsRepository(_db);
        }

        public virtual IEnumerable<FaqDto> FaqBriefs { get; set; }

        public virtual IEnumerable<FaqDto> SubFaqDtos(int parentId)
        {
            return _faqsRepository.GetSubFaqsSorted(parentId);
        }
    }
}

Thanks again VjSoft - I didn't think I would get this going today.

RBS
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .N…
The object model of .Net can be overwhelming at times – so overwhelming that quite trivial tasks often take hours of research. In this case, the task at hand was to populate the datagrid from SQL Server database in Visual Studio 2008 Windows applica…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now