ASP.NET Core 8 MVC中实现全局帖子分类过滤器的方案问询
全局帖子分类过滤器实现方案
需求背景
现有网站帖子分类筛选功能通过FilterController的Index动作实现,需将其改造为全局过滤器,让所有依赖_context.Posts展示数据的控制器,直接使用筛选后的数据集替代原始的_context.Posts。
实现步骤
1. 创建全局Action过滤器
实现一个继承IActionFilter的过滤器类,在请求进入控制器动作前完成帖子筛选,并将结果存入HttpContext.Items供控制器取用:
public class PostCategoryFilter : IActionFilter { private readonly ApplicationDbContext _context; private readonly IMemoryCache _cache; public PostCategoryFilter(ApplicationDbContext context, IMemoryCache cache) { _context = context; _cache = cache; } public void OnActionExecuting(ActionExecutingContext context) { // 从缓存读取当前选中的分类,默认显示全部 var postCategory = _cache.GetString("CurrentPostCategory") ?? "All"; IQueryable<Post> filteredPosts = _context.Posts; if (postCategory != "All" && !string.IsNullOrEmpty(postCategory)) { filteredPosts = filteredPosts.Where(p => p.PostCategory == postCategory); } // 将筛选后的数据集存入HttpContext,供后续控制器使用 context.HttpContext.Items["FilteredPosts"] = filteredPosts; } public void OnActionExecuted(ActionExecutedContext context) { // 可选:执行动作后的清理或补充逻辑 } }
2. 注册全局过滤器
在Program.cs中配置MVC时,将过滤器添加为全局过滤器:
builder.Services.AddControllersWithViews(options => { options.Filters.Add<PostCategoryFilter>(); });
3. 简化FilterController逻辑
原FilterController无需再处理筛选逻辑,仅负责更新缓存中的当前分类,然后跳转回来源页:
public async Task<IActionResult> Index(string postCategory) { // 处理空值,默认设为"All" var validCategory = string.IsNullOrEmpty(postCategory) ? "All" : postCategory; _cache.Set("CurrentPostCategory", validCategory); // 跳转回来源页,无来源则跳主页 string refererUrl = Request.Headers["Referer"].ToString(); return Redirect(string.IsNullOrEmpty(refererUrl) ? "/" : refererUrl); }
4. 修改业务控制器使用筛选后的数据
将控制器中原本调用_context.Posts的地方,替换为从HttpContext.Items获取的筛选数据集:
[HttpGet] public async Task<IActionResult> Index() { var filteredPosts = HttpContext.Items["FilteredPosts"] as IQueryable<Post>; return View(await filteredPosts.ToListAsync()); }
5. 可选:封装扩展方法简化调用
为HttpContext编写扩展方法,避免控制器中重复的类型转换:
public static class HttpContextExtensions { public static IQueryable<Post> GetFilteredPosts(this HttpContext context) { return context.Items["FilteredPosts"] as IQueryable<Post> ?? throw new InvalidOperationException("全局帖子分类过滤器未正确初始化"); } }
控制器中即可简化为:
[HttpGet] public async Task<IActionResult> Index() { return View(await HttpContext.GetFilteredPosts().ToListAsync()); }
内容的提问来源于stack exchange,提问作者ZNAXNOR
相关产品推荐
相关产品推荐

