ASP.NET Core Web API 如何仅向已登录用户展示其所属的Mandate数据
解决方案
步骤1:注册IHttpContextAccessor服务(用于获取当前登录用户ID)
在.NET 6+的Program.cs中添加服务注册:
builder.Services.AddHttpContextAccessor();
步骤2:在MandateService中注入服务,实现获取当前登录用户ID的逻辑
修改MandateService的构造函数,注入IHttpContextAccessor,同时新增获取当前用户ID的方法:
using System.Security.Claims; using Microsoft.AspNetCore.Http; private readonly IHttpContextAccessor _httpContextAccessor; // 构造函数新增注入参数 public MandateService(IUnitOfWork unitOfWork, IUriPaginationService uriPaginationService, IHttpContextAccessor httpContextAccessor) { _unitOfWork = unitOfWork; _uriPaginationService = uriPaginationService; _httpContextAccessor = httpContextAccessor; } // 获取当前登录用户ID private int? GetCurrentUserId() { var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (int.TryParse(userIdClaim, out int userId)) { return userId; } // 未登录或Claim不存在则返回空 return null; }
注意:如果你的登录逻辑使用自定义Claim存储用户ID,需要将
ClaimTypes.NameIdentifier替换为你自定义的Claim类型。
步骤3:扩展仓储接口支持筛选和关联查询
在IBaseRepository新增支持筛选和Include导航属性的方法,方便后续条件查询:
// IBaseRepository接口新增方法定义 public interface IBaseRepository<T> where T : EntityBase { // 原有方法保留,新增如下方法 Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, params Expression<Func<T, object>>[] includes); } // BaseRepository中实现该方法 public async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, params Expression<Func<T, object>>[] includes) { IQueryable<T> query = _context.Set<T>(); // 加载关联导航属性 if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); } // 应用筛选条件 if (filter != null) { query = query.Where(filter); } return await query.ToListAsync(); }
步骤4:修改MandateService查询逻辑,过滤用户关联数据
调整GetAll和GetMandates方法的查询逻辑,只返回当前用户关联的Mandate数据:
public async Task<ResponsePagination<GenericPagination<MandateGetDto>>> GetAll(int page, int sizeByPage) { string nextRoute = null, previousRoute = null; var currentUserId = GetCurrentUserId(); // 未登录直接返回空结果 if (!currentUserId.HasValue) { var emptyPagination = GenericPagination<MandateGetDto>.Create(new List<MandateGetDto>(), page, sizeByPage); return new ResponsePagination<GenericPagination<MandateGetDto>>(emptyPagination); } // 过滤规则:Mandate关联的Merchant的UserId等于当前登录用户ID IEnumerable<Mandate> data = await _unitOfWork.MandateRepository.GetAsync( filter: m => m.Merchant.UserId == currentUserId.Value, includes: m => m.Merchant ); // 后续原有映射、分页逻辑保持不变 var mapper = new EntityMapper(); var mandatesDto = data.Select(m => mapper.FromMandateToMandateGetDto(m)).ToList(); GenericPagination<MandateGetDto> objGenericPagination = GenericPagination<MandateGetDto>.Create(mandatesDto, page, sizeByPage); ResponsePagination<GenericPagination<MandateGetDto>> response = new ResponsePagination<GenericPagination<MandateGetDto>>(objGenericPagination); response.CurrentPage = objGenericPagination.CurrentPage; response.HasNextPage = objGenericPagination.HasNextPage; response.HasPreviousPage = objGenericPagination.HasPreviousPage; response.PageSize = objGenericPagination.PageSize; response.TotalPages = objGenericPagination.TotalPages; response.TotalRecords = objGenericPagination.TotalRecords; response.Data = objGenericPagination; if (response.HasNextPage) { nextRoute = $"/mandates?page={(page + 1)}"; response.NextPageUrl = _uriPaginationService.GetPaginationUri(page, nextRoute).ToString(); } else { response.NextPageUrl = null; } if (response.HasPreviousPage) { previousRoute = $"/mandates?page={(page - 1)}"; response.PreviousPageUrl = _uriPaginationService.GetPaginationUri(page, previousRoute).ToString(); } else { response.PreviousPageUrl = null; } return response; } // 同理修改GetMandates方法 public async Task<IEnumerable<Mandate>> GetMandates() { var currentUserId = GetCurrentUserId(); if (!currentUserId.HasValue) { return Enumerable.Empty<Mandate>(); } return await _unitOfWork.MandateRepository.GetAsync( filter: m => m.Merchant.UserId == currentUserId.Value, includes: m => m.Merchant ); }
优化建议
如果数据量较大,可以将分页逻辑下移到数据库层面执行,避免先查询全量数据再在内存分页,减少内存占用和查询耗时。
内容的提问来源于stack exchange,提问作者Olugbenga
相关产品推荐
相关产品推荐

