如何让ActionFilter同时兼容ASP.NET MVC与WebAPI框架?
ASP.NET MVC与WebAPI白名单过滤器复用方案
由于ASP.NET MVC和WebAPI是两个独立的框架,它们的ActionFilterAttribute分别属于System.Web.Mvc和System.Web.Http命名空间,基类与执行上下文完全不同,无法通过单个过滤器类同时兼容两者。
最合理的解决方式是将白名单校验的核心逻辑抽离到独立的共享类中,再分别编写对应MVC和WebAPI的过滤器类,通过调用共享类的逻辑实现代码复用。
具体实现步骤:
编写共享校验类
把白名单判断的核心逻辑单独封装,提供适配MVC和WebAPI请求对象的方法:public class WhitelistChecker { // 白名单配置,可从配置文件读取 private readonly HashSet<string> _allowedIps = new HashSet<string> { "127.0.0.1", "192.168.1.100" }; private readonly HashSet<string> _allowedDomains = new HashSet<string> { "your-allowed-domain.com" }; // 适配MVC的HttpRequestBase public bool IsRequestAllowed(HttpRequestBase request) { string clientIp = request.UserHostAddress; string clientDomain = request.UrlReferrer?.Host; return _allowedIps.Contains(clientIp) || (clientDomain != null && _allowedDomains.Contains(clientDomain)); } // 适配WebAPI的HttpRequestMessage public bool IsRequestAllowed(HttpRequestMessage request) { // 从HttpRequestMessage获取客户端IP string clientIp = request.Properties["MS_HttpContext"] is HttpContextBase context ? context.Request.UserHostAddress : request.GetOwinContext()?.Request.RemoteIpAddress; // 获取请求来源域名 string clientDomain = request.Headers.Referrer?.Host; return _allowedIps.Contains(clientIp) || (clientDomain != null && _allowedDomains.Contains(clientDomain)); } }编写MVC专属过滤器
继承MVC的ActionFilterAttribute,调用共享类的校验逻辑:using System.Web.Mvc; public class MvcWhitelistFilter : ActionFilterAttribute { private readonly WhitelistChecker _checker = new WhitelistChecker(); public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!_checker.IsRequestAllowed(filterContext.HttpContext.Request)) { filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Forbidden); } base.OnActionExecuting(filterContext); } }编写WebAPI专属过滤器
继承WebAPI的ActionFilterAttribute,同样调用共享类:using System.Web.Http.Controllers; using System.Web.Http.Filters; public class WebApiWhitelistFilter : ActionFilterAttribute { private readonly WhitelistChecker _checker = new WhitelistChecker(); public override void OnActionExecuting(HttpActionContext actionContext) { if (!_checker.IsRequestAllowed(actionContext.Request)) { actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden); } base.OnActionExecuting(actionContext); } }
补充说明:
如果你的白名单校验属于授权逻辑,也可以选择继承MVC的AuthorizeAttribute或WebAPI的AuthorizeAttribute来实现,核心思路仍是将校验逻辑抽离到共享类,避免重复代码。这种方式更符合授权场景的语义,但实现原理和上述方案一致。
内容的提问来源于stack exchange,提问作者Virus721
相关产品推荐
相关产品推荐

