如何通过MVC ActionFilter为所有请求添加自定义查询参数?遇集合异常
解决ActionFilter中添加自定义查询参数时的NotSupportedException问题
嘿,我一眼就看出你遇到的问题了——你直接去操作RouteData.Values.Keys和Request.Query.Keys这些只读/固定大小的集合,当然会抛NotSupportedException啦!这些集合的设计就是不允许直接添加键的,得换个思路来实现需求。
先给你理清楚核心问题:
RouteData.Values.Keys是只读集合,不能直接调用Add方法Request.Query也是只读的,同样不允许修改原集合
接下来分两种场景给你解决方案:
场景1:需要修改地址栏URL(让用户看到带参数的URL)
如果要让访问的URL自动带上自定义参数(比如从/变成/?customPara=xxx),你需要在动作执行前做重定向,生成包含新参数的URL再跳转。代码示例如下:
public class CustomActionFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var request = filterContext.HttpContext.Request; var urlHelper = new UrlHelper(filterContext.RequestContext); // 把原查询参数转成可修改的Dictionary var queryParams = request.QueryString.ToDictionary(kv => kv.Key, kv => kv.Value); // 只在参数不存在时添加,避免重复 if (!queryParams.ContainsKey("customPara")) { queryParams.Add("customPara", "myAllcustomparamter"); } // 生成包含新参数的完整URL var newUrl = urlHelper.Action( filterContext.ActionDescriptor.ActionName, filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, new RouteValueDictionary(queryParams), request.Url.Scheme, request.Url.Host ); // 执行临时重定向(302),如果需要永久重定向可以用 RedirectToRouteResult 或者修改状态码 filterContext.Result = new RedirectResult(newUrl); } }
这里用OnActionExecuting而不是OnActionExecuted的原因是:在动作执行前就重定向,避免白跑一趟执行不必要的业务逻辑,效率更高。
场景2:不需要修改地址栏,仅让后续逻辑获取参数
如果只是想让控制器动作或者后续中间件能拿到这个自定义参数,不需要改变用户看到的URL,那可以把参数加到RouteData或者HttpContext.Items里,代码更简单:
public class CustomActionFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { // 方式1:添加到RouteData,后续可以通过 RouteData.Values["customPara"] 获取 if (!filterContext.RouteData.Values.ContainsKey("customPara")) { filterContext.RouteData.Values.Add("customPara", "myAllcustomparamter"); } // 方式2:添加到HttpContext.Items,更灵活,适合跨中间件传递 filterContext.HttpContext.Items["customPara"] = "myAllcustomparamter"; } }
为什么你的原代码报错?
再回头看你写的代码:
filterContext.RouteData.Values.Keys.Add("customPara"); filterContext.HttpContext.Request.Query.Keys.Add("customPara=myAllcustomparamter");
这里的问题是:Keys集合是只读的,它是集合内部维护的视图,不允许外部直接添加元素。正确的做法是直接对键值对集合做操作(比如Values.Add(key, value)),而不是去操作Keys属性。
内容的提问来源于stack exchange,提问作者Kalpesh Boghara
相关产品推荐
相关产品推荐

