This is my UserIndex.cshtml view for a page which lists all posts that belong to the currently logged in user.
@model IEnumerable<AProject.Areas.Identity.Data.Post>
@using Microsoft.AspNetCore.Identity
@using AProject.Areas.Identity.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h3> My posts </h3>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.DateCreated)
</th>
<th>
@Html.DisplayNameFor(model => model.Category)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
@if( @UserManager.GetUserName(User) == item.User.UserName )
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateCreated)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category.Name)
</td>
<td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
Apparently there is an error in the line with the @if( @UserManager.GetUserName(User) == item.User.UserName )
: NullReferenceException: Object reference not set to an instance of an object. I have no clue why I have this error because everything worked for a while (it listed in the table only posts by the logged in user ) then I was working on another view and when I got back to this page there was an error. I even tried with this @if( @User.Identity.Name == item.User.UserName )
but there is still an error. I even undid all the changes I made before the error and it still doesn't work. Also here is my controller if it helps:
[Authorize]
public class PostsController : Controller
{
private readonly AProjectContext _context;
private readonly UserManager<ApplicationUser> _userManager;
public PostsController(AProjectContext context, UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
// GET: Posts
public async Task<IActionResult> Index()
{
var aprojectContext = _context.Posts.Include(p => p.Category).Include(p => p.User);
return View(await aprojectContext.ToListAsync());
}
public async Task<IActionResult> UserIndex()
{
var aprojectContext = _context.Posts.Include(p => p.Category).Include(p => p.User);
return View(await aprojectContext.ToListAsync());
}
// GET: Posts/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts
.Include(p => p.Category)
.Include(p => p.User)
.FirstOrDefaultAsync(m => m.Id == id);
if (post == null)
{
return NotFound();
}
return View(post);
}
// GET: Posts/Create
public IActionResult Create()
{
ViewData["CategoryId"] = new SelectList(_context.Set<Category>(), "Id", "Name");
return View();
}
// POST: Posts/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,Summary,Content,CategoryId")] Post post)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var userName = User.FindFirstValue(ClaimTypes.Name);
ApplicationUser appUser = await _userManager.GetUserAsync(User);
string userEmail = appUser?.Email;
post.DateCreated = DateTime.Now;
post.User = appUser;
post.UserId = userId;
if (ModelState.IsValid)
{
_context.Add(post);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["CategoryId"] = new SelectList(_context.Set<Category>(), "Id", "Name", post.Category.Name);
return View(post);
}
// GET: Posts/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts
.Include(p => p.Category)
.Include(p => p.User)
.FirstOrDefaultAsync(m => m.Id == id);
if (post == null)
{
return NotFound();
}
ViewData["CategoryId"] = new SelectList(_context.Set<Category>(), "Id", "Name", post.Category.Name);
return View(post);
}
// POST: Posts/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,Summary,Content,CategoryId")] Post post)
{
if (id != post.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(post);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PostExists(post.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["CategoryId"] = new SelectList(_context.Set<Category>(), "Id", "Name", post.Category.Name);
return View(post);
}
// GET: Posts/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var post = await _context.Posts
.Include(p => p.Category)
.Include(p => p.User)
.FirstOrDefaultAsync(m => m.Id == id);
if (post == null)
{
return NotFound();
}
return View(post);
}
// POST: Posts/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var post = await _context.Posts.FindAsync(id);
_context.Posts.Remove(post);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool PostExists(int id)
{
return _context.Posts.Any(e => e.Id == id);
}
Is there a way to filter the posts by the currently logged in user in the controller then sending those posts to the view, instead filtering all posts in the view, if this still doesn't work?
**** UPDATE ****
It turns out the problem wasn't @UserManager.GetUserName(User)
but the item.User.UserName
because Post item didn't have a User. It works now. Also, if anyone has similar problems, I found it is better to filter posts in the controller which now looks like this
public async Task<IActionResult> UserIndex()
{
var userName = User.FindFirstValue(ClaimTypes.Name); // will give the user's userName
var aprojectContext = _context.Posts.Include(p => p.Category).Include(p => p.User).Where(p => p.User.UserName == userName);
return View(await aprojectContext.ToListAsync());
}
Thanks everyone for suggestions and help.