繁体   English   中英

ASP.NET 核心 MVC 身份 - 如何查看当前登录的用户?

[英]ASP.NET Core MVC Identity - how to get current logged in user in view?

这是我的 UserIndex.cshtml 视图,其中列出了属于当前登录用户的所有帖子。

@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>

显然, @if( @UserManager.GetUserName(User) == item.User.UserName )行中存在错误:NullReferenceException: Object 引用未设置为 object 的实例。 我不知道为什么会出现此错误,因为一切都工作了一段时间(它仅在表中列出了登录用户的帖子)然后我正在处理另一个视图,当我返回此页面时出现错误。 我什至尝试过这个@if( @User.Identity.Name == item.User.UserName ) ,但仍然有错误。 我什至撤消了我在错误之前所做的所有更改,但它仍然不起作用。 如果有帮助,这里还有我的 controller:

[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);
        }
    

有没有办法过滤 controller 中当前登录用户的帖子,然后将这些帖子发送到视图,而不是过滤视图中的所有帖子,如果这仍然不起作用?

**** 更新 ****

事实证明问题不是@UserManager.GetUserName(User) ,而是item.User.UserName ,因为Post 项目没有用户。 现在可以了。 另外,如果有人有类似的问题,我发现最好过滤 controller 中的帖子,现在看起来像这样

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());
        }

感谢大家的建议和帮助。

您可以做的最好的是将 UserId 保存为帖子的字段。 然后,您从身份服务器中的 Ali Kianoor 提到的令牌/声明中获取此 UserId,您可以根据 UserId 过滤帖子。

O 并确保在业务逻辑/控制器中而不是在您的视图中执行此操作。 您需要在 MVC 中的视图和 Controller 之间明确区分关注点。

在此处阅读有关 SOC 的更多信息

如果您的 session 超时并且您需要重新登录,则会发生这种情况。

更好的重构方法是在后端 controller 上进行用户过滤。 在您的 controller 中获取 session 用户,并将 Where 语句添加到您的 aprojectContext 创建中。 如何在 asp.net 内核中获取当前用户

试试这个来获取 userId:

string userId = User.Claims.First(c => c.Type == "UserID").Value;

对于获取用户帖子,您应该在表/视图中添加一列,该列正在处理每个帖子的 userId,然后您可以根据需要过滤表/视图。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM