0

I'm building a site that is basically a blog host. Users can write stories and other users can read and comment on them. User can read any story (currently) whether they're logged in or not, but can only comment on stories if they have an account and are logged in.

When I'm logged in, this works. I pass the comments associated with the story to the viewmodel and run a foreach loop through the comments in the model to print them out. I have a property of IsAnonymous that checks if the person is logged in or not, then I have another property that is IsAuthorOfComment so that I can print the edit/delete comment functions if the logged in person also wrote the comment.

This works fine if you're logged in. If you're not, I get an Object reference not set to an instance of an object. In the debugger, I see that two valid comments are being passed to the view and I can't find any property in them which is null to cause this error.

enter image description here

enter image description here

enter image description here

My controller action

[HttpGet]
[AllowAnonymous]
public ActionResult Details(int id)
    {
    bool isAnonymous;

    var FoundStory = _dbContext.Stories.SingleOrDefault(x => x.Id == id);

    if (FoundStory == null)
    {
        return HttpNotFound();
    }

    //get the logged in userId
    string signedInUserId = User.Identity.GetUserId();

    //if the person reading the article isn't signed in, the userId will come back null
    //need to guard against this in view so the view doesn't break
    //this is here because in the view, we want to display a comment box if the user is signed in, and
    //if they're not signed in, redirect them to the log-in page
    //check to see if the user is reading the article anonymously
    //if the user is anonymous, set isAnonymous to true and do not pass the user to the IsCommenter function call
    //if the user is not anonymous, set isAnonymous to false and pass the user to the IsCommenter function
    if (signedInUserId == null)
    {
        isAnonymous = true;

    } else
    {
        isAnonymous = false;
    }

    var SignedInUser = _dbContext.Users.SingleOrDefault(x => x.Id == signedInUserId);

    var comments = _dbContext
        .Comments
        .Where(x => x.StoryId == FoundStory.Id)
        .OrderByDescending(x => x.LastUpdated)
        .ToList();

//helper.IsCommenter compares a comments authorid to the signed in user's id, we need to
//must ensure the user is not anonymous and that the comments returned are equal or greater than one otherwise helper.IsCommenter may throw an exception
    if (!isAnonymous && comments.Count() >= 1)
    {
        helper.IsAuthorOfComment(comments, SignedInUser);
    }

    var viewModel = new StoryDetailsViewModel
    {
        IsAnonymous = isAnonymous,
        StoryId = FoundStory.Id,
        AuthorId = FoundStory.AuthorId,
        Story = FoundStory,
        User = SignedInUser,
        Comments = comments
    };

    return View(viewModel);
}
J.G.Sable
  • 1,258
  • 4
  • 26
  • 62
  • Exception says it all, User property is null. – just-my-name Oct 26 '18 at 16:46
  • @just-my-name is right. When you call `SingleOrDefault` to get the user, if a single record is not found, it returns null. You need to null check the `User` property in your view. Better yet, create a new class to only contain the `User` information you need and pass that to the view model. It's not typically a good practice to pass Entity objects to the view. – Aaron Oct 28 '18 at 12:42

0 Answers0