0

I came up with the scenario that i m getting multiple question and there option MCQ's using single id i want to show random question on Partial view and when user click next button it should load another random question using MVC EF. Here is my code.

var modeldata =
                Db.ExamQuestions.Include("ListofOptions").Where(x => x.FkExamId == model.ExamId).Select(q => new QuestionViewModel
                {
                    QuestionId = q.ID,
                    QuestionDescription = q.QuestionDescription,
                    ExamId = q.FkExamId,
                    CorrectOption = q.CorrectOption,
                    ListofOption = q.ListofOptions.Select(o => new QuestionOptionViewModel
                    {
                        OptionA = o.OptionA,
                        OptionB = o.OptionB,
                        OptionC = o.OptionC,
                        OptionD = o.OptionD

                    }).ToList()
                }).OrderBy(q => q.QuestionId).Take(1).ToList();
  • Create a random number between 0 and the `.Count` of the collection and use `.Skip()` but that is no guarantee that the same question wont be returned again. –  Nov 28 '16 at 07:24
  • Can you please provide me code ? – Muhammad Kamran Nov 28 '16 at 08:00
  • I have achieved by using skip but how to prevent single question from repeatition – Muhammad Kamran Nov 28 '16 at 10:50
  • You have to keep a record of what has been previously viewed - but why not just return them in order (and increment a value for the index in each button click)? –  Nov 28 '16 at 10:53

1 Answers1

0

Option1. Give random number to every row in ViewModel

If you are tring to show data of different order. Set a random number on every record of the viewModel, and pass the viewModel to the View.

Random rnd = new Random();
var modeldata =
            Db.ExamQuestions.Include("ListofOptions").Where(x => x.FkExamId == model.ExamId).Select(q => new QuestionViewModel
            {
                QuestionId = q.ID,
                QuestionDescription = q.QuestionDescription,
                ExamId = q.FkExamId,
                CorrectOption = q.CorrectOption,
                ListofOption = q.ListofOptions.Select(o => new QuestionOptionViewModel
                {
                    OptionA = o.OptionA,
                    OptionB = o.OptionB,
                    OptionC = o.OptionC,
                    OptionD = o.OptionD
                }).ToList(),
                RndOrder = rnd.Next(1, maxNumber)
            }).OrderBy(q => q.RndOrder).ToList();

Option2. Get random rows from database, render partialView

Controller : Get random question's id list from database and create another HttpGet method for returning _PartialView.

public ActionResult Random()
    {
        int maxCnt = 5; //The max number of questions for user
        ViewBag.QsIds = (new TmsDbContext()).Database
            .SqlQuery<MyQuestion>($"SELECT TOP {maxCnt} * FROM MyQuestions ORDER BY NEWID()")
            .Select(x=> x.Id).ToList();
        return View();
    }

    [HttpGet]
    [Route("GetPartailView/{id}")]
    public ActionResult GetPartialView(int id)
    {
        var viewModel = (new DbContext()).MyQuestions.Find(id);
        return PartialView("~/Views/Home/_PartialView.cshtml", viewModel);
    }

_PartialView : Shows A question

@model MyQuestion 
<span>@Model.Title</span>

View : Ajax and render the _PartialView of current question

<input type="button" value="Next"  id="next"/>
<div id="qsDiv"></div>
<script>
$(function (){ 
    var qsIds = [];
    var array = @Html.Raw(Json.Encode(@ViewBag.QsIds));

    for(var i = 0; i < array.length; i++) {
        qsIds[i] = array[i];
    }

    var getPartialViewUrl = "/Home/GetPartialView/";
    var index = 0;

    $("#next").click(function () {
        $.ajax({
            dataType: "html",
            url: getPartialViewUrl + qsIds[index],
            success: function (html) {
                $("#qsDiv").html("");
                $("#qsDiv").append(html);
                index++; 
            }
        })
    })
});
</script>
KarateJB
  • 941
  • 2
  • 10
  • 22