locked
ArgumentNullException: Value cannot be null - problem in LINQ - couldn't find the reason RRS feed

  • Question

  • User1255309776 posted

    Hi,

    I develop a quiz application where the score for each question is calculated according to remained time. I get ArgumentNull Exception in my Question (post) action, but don't know why as I didn't see null parameter. Please, assist to find solution. Here is the details:

    View:

    @model Intellect.Models.ViewModels.AdminViewModel
    
        @{
            Layout = "AdminLayout";
        }
    
        <div class="questioncontainer">        
            <form asp-action="Question" asp-controller="Home" asp-route-id="@Model.NextQuestion.Id" asp-route-count="@ViewBag.Equestions">
                <div class="row">
                    <div class="col-lg-3"></div>
                    <div class="col-lg-6 col-sm-12">
                        <table>
                            <tr>
                                <th>Qaliq vaxt</th>
                            </tr>
                            <tr>
                                <td>
                                    <input asp-for="Question.Score" id="time" name="timer" />
                                </td>
                            </tr>
                        </table>
                        <div class="question">@Model.CurrentQuestion.Description </div>
                    </div>
                    <div class="col-lg-3"></div>
                </div>
                <div class="row">
                    <div class="col-lg-3 col-sm-12">
                    @foreach (Answer item in Model.Answers)
                    {
                                <input asp-for="@item.Id" name="@item.Id" hidden />
                                <input type="radio" asp-for="@item.Id" name="myanswer" value="@item.Id" />@item.Description
    
                                <br>                 
                    }
    </div>
                    <div class="col-lg-3"></div>
                </div>
                <div class="row">
                    <div class="col-lg-6 col-sm-4">
    
                    </div>
                    <div class="col-lg-3 col-sm-4">
    
                    </div>
                    <div class="col-lg-3 col-sm-4">
                        <div class="nextbtn">
                            @if (ViewBag.Equestions == 0)
                            {
                                <input type="submit" value="Finish" />
                            }
                            else
                            {
                                <input type="submit" value="Next" />
                            }
    
                        </div>
                    </div>
                </div>
            </form>
    
        </div>
    
    @section Script{ 
        <script>
            function StartTimer(seconds) {
                var intSeconds = seconds;
                var timer = setInterval(myTimer, 1000);
                function myTimer() {
                    if (intSeconds < 0) {
                        Alert("bitdi")
                        clearInterval(timer)
                        return;
                    }
                    document.getElementById("time").value = intSeconds;
                    intSeconds--;
                }
            }
            StartTimer(60);
    
        </script>
    }

    While running the application, I get the following error after submitting the Next button:  https://prnt.sc/sdoiul

    Here is the Controller

     [HttpGet]
            public async Task<IActionResult> Question(int Id, int count)
            {
                AdminViewModel admodel = new AdminViewModel();
                admodel.CurrentQuestion = await _intellectDbContext.Questions.Where(x => x.Id == Id).SingleOrDefaultAsync();
                admodel.Answers = await _intellectDbContext.Answers.Where(y => y.QuestionId == Id).ToListAsync();
                admodel.Equestions = await _intellectDbContext.Questions.Where(q => q.ExamId == exam_id).ToListAsync();
    
                if (count > 1)
                {
                    var question = RemainedQuestions.Single(r => r.Id == admodel.CurrentQuestion.Id);
                    PreviousId = question.Id;
                    RemainedQuestions.Remove(question);
                    admodel.NextQuestion = RemainedQuestions[0];
                    count -= 1;
                }
                else
                {
                    admodel.NextQuestion = RemainedQuestions[0];
                    count -= 1;
                }
    
                if (count == -1)
                {
                    return RedirectToAction(nameof(Finish));
                }
    
                ViewBag.Equestions = count;
    
                return View(admodel);
            }
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public async Task<IActionResult> Question(int Id, int count, int myanswer, int timer)
            {
                AdminViewModel admodel = new AdminViewModel();
                admodel.CurrentQuestion = await _intellectDbContext.Questions.Where(x => x.Id == Id).SingleOrDefaultAsync();
                admodel.Answers = await _intellectDbContext.Answers.Where(y => y.QuestionId == Id).ToListAsync();
                admodel.Equestions = await _intellectDbContext.Questions.Where(q => q.ExamId == exam_id).ToListAsync();
    
                correctAnswer = _intellectDbContext.Answers.Where(a => a.QuestionId == PreviousId && a.Correct == true).SingleOrDefault().Id;
    
                if (_signInManager.IsSignedIn(User))
                {
                    ExamUser examTaker = await _userManager.GetUserAsync(HttpContext.User);
    
                    examTaker.TestTaker = await _intellectDbContext.TestTakers.FirstOrDefaultAsync();
                                     
                    admodel.CurrentQuestion = examTaker.TestTaker.UserQuestions.Select(u => u.Question).Where(x => x.Id == Id).SingleOrDefault();
                    if (myanswer == correctAnswer)
                    {
                        admodel.CurrentQuestion.Score = timer;
                        await _intellectDbContext.SaveChangesAsync();
                        // admodel.CurrentQuestion.Score = result;
                    }
                }
                 
                    if (count > 1)
                {
                    var question = RemainedQuestions.Single(r => r.Id == admodel.CurrentQuestion.Id);
                    PreviousId = question.Id;
                    RemainedQuestions.Remove(question);
                    admodel.NextQuestion = RemainedQuestions[0];
                    count -= 1;
                }
                else
                {
                    admodel.NextQuestion = RemainedQuestions[0];
                    count -= 1;
                }
    
                if(count == -1)
                {
                    return RedirectToAction(nameof(Finish));
                }
    
                ViewBag.Equestions = count;
    
                return RedirectToAction(nameof(Question));
            }
    Saturday, May 9, 2020 12:39 PM

All replies

  • User475983607 posted

    Generally, the error message shows the line of code that caused the null exception as well as the item that's null.  If you run the code through the debugger, you will also find the line of code that caused the null exception and can see the null value.

    Please do basic troubleshooting rather than dumping code on the forum that has many potential issues.

    Saturday, May 9, 2020 12:59 PM
  • User1255309776 posted

    If you click on the link I provided, you can see the line:

    118 admodel.CurrentQuestion = examTaker.TestTaker.UserQuestions.Select(u => u.Question).Where(x => x.Id == Id).SingleOrDefault();

    But the thing is that there is no such argument that could be null.

    Saturday, May 9, 2020 1:07 PM
  • User475983607 posted

    FaridGN

    If you click on the link I provided, you can see the line:

    118 admodel.CurrentQuestion = examTaker.TestTaker.UserQuestions.Select(u => u.Question).Where(x => x.Id == Id).SingleOrDefault();

    But the thing is that there is no such argument that could be null.

    The error states UserQuestion (source) is null.   Keep in mind that you are the only person that can reproduce so you need to learn how to debug your code.

    Open SQL Management Studio and query the data.  It seems you are missing data or there is a problem with the design.

    Saturday, May 9, 2020 2:26 PM
  • User1255309776 posted

    Yes, but UserQuestion table has this question id, and it's linked to that TestTaker whose Id is 10 in UserQuestion table.

    UserQuestion is the moderate table between TestTakers and Questions where there is many-to-many relationship between testTaker and Question. The UserQuestion table is like thisin SQL Server:

    TestTakerId QuestionID
    10 1
    10 2
    10 3
    10 4
    10 5

    All the questions of particular quiz is linked to TestTaker with the Id 10.

    For detailed info, you can see my relevant models:

    Question

    public class Question
        {
            public Question()
            {
                Answers = new HashSet<Answer>();
            }
    
            public int Id { get; set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public Exam Exam { get; set; }
            public int ExamId { get; set; }
            public TimeSpan? Remainedtime { get; set; }
            public int Score { get; set; }
            public ICollection<Answer> Answers { get; set; }
            public ICollection<UserQuestion> UserQuestions { get; set; }
    
        }    

    TestTaker

     public class TestTaker
        {
            public int Id { get; set; }
            [Required]
            public string Name { get; set; }
            public string Phone { get; set; }
            public string Education { get; set; }
            public string Job { get; set; }
            public DateTime Birth { get; set; }
            public ExamUser ExamUser { get; set; }
            public int Result { get; set; }
            public ICollection<UserQuestion> UserQuestions { get; set; }
        }

    UserQuestion

     public class UserQuestion
        {
            public int TestTakerId { get; set; }
            public TestTaker TestTaker { get; set; }
            public int QuestionId { get; set; }
            public Question Question { get; set; }
        }

    DbContext

     public class IntellectDbContext:IdentityDbContext<ExamUser>
        {
            public IntellectDbContext(DbContextOptions<IntellectDbContext> dbContextOptions) : base(dbContextOptions)
            {
    
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Entity<UserQuestion>()
                    .HasKey(a => new { a.TestTakerId, a.QuestionId });
    
                modelBuilder.Entity<UserQuestion>()
                    .HasOne(a => a.TestTaker)
                    .WithMany(b => b.UserQuestions)
                    .HasForeignKey(a => a.TestTakerId);
    
                modelBuilder.Entity<UserQuestion>()
                    .HasOne(a => a.Question)
                    .WithMany(c => c.UserQuestions)
                    .HasForeignKey(a => a.QuestionId);
                
              
            }
    
            public DbSet<Answer> Answers { get; set; }
            public DbSet<Question> Questions { get; set; }
            public DbSet<Exam> Exams { get; set; }
            public DbSet<ExamUser> ExamUsers { get; set; }
            public DbSet<UserQuestion> UserQuestions { get; set; }
            public DbSet<TestTaker> TestTakers { get; set; }
        }

    Saturday, May 9, 2020 4:28 PM
  • User1255309776 posted

    I have found the problem in this code:   admodel.CurrentQuestion = examTaker.TestTaker.UserQuestions.Select(u => u.Question).Where(x => x.Id == Id).SingleOrDefault();

    CurrentQuestion is type of Question, and right side gives me UserQuestion type. I corrected like below: 

    admodel.CurrentQuestion = await _intellectDbContext.Questions.Include(q => q.UserQuestions).Where(u => u.Id == Id).SingleOrDefaultAsync();

    But this time I faced with SQLException: https://prnt.sc/sdverp

    Actually, I know the reason, but cannot write relevant LINQ so that it would both join UserQuestions to Questions and TestTakers in order to point QuestionId to relevant TestTakerId who is signed in. For each testTaker where will be different score of the same question. It must detect each question for relevant test takers who take test even simultaneously. Any Idea?

    Saturday, May 9, 2020 8:58 PM