我可以修改Request.Form变量吗?

13
我尝试使用Request.Form.Set(k, v)方法,但它抛出异常。

集合是只读的。

2个回答

13

这与修改 Request.Querystring 的操作完全相同。两者都包含了私有属性和一个可能被认为是bug的内部复杂结构,但我知道两种可能的解决方案(我会立刻排除response.redirect计划 - 那太糟糕了)。

方法一是使用反射直接修改集合:

NameValueCollection oQuery = Request.QueryString;
oQuery = (NameValueCollection)Request.GetType().GetField("_queryString",BindingFlags.NonPublic | BindingFlags.Instance).GetValue(Request);
PropertyInfo oReadable = oQuery .GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
oReadable.SetValue(oQuery, false, null);
oQuery["foo"] = "bar";
oReadable.SetValue(oQuery, true, null); 

我认为更适合单元测试的备选方案是计划B,它避免直接处理集合,而是将其作为NameValueCollection传递给任何要处理它的方法,并浅复制你所需要的内容。我自己使用这种方法来模拟Web请求。

编辑:Marc Gravell提供了更为优美的计划B理由。


2
以这种方式操纵私有内容绝不是建议的做法,应尽可能避免(几乎等于不要这样做)。毕竟,它们被设置为私有是有原因的。您将依赖于库的特定版本。底层实现的任何更改都可能破坏您的应用程序。 - Mehrdad Afshari
你会看到我倡导备选方案B。 - annakata
计划A错过了一些细节。我认为这不是正确的方式。你可以自己测试。 - Joe.wang
不要使用“计划A”。它与Mono不兼容,即使可能被认为是“不相关的”,它仍然表明该代码存在一些非常糟糕的问题,因此不应该这样做。 - Tobias81

1
表单是客户端发送请求的表示形式。你想要做什么?个人建议将“读取表单”代码与“对值进行处理”的代码分开,这样可以在早期进行任何预处理(从表单中读取时),后续的代码不需要知道实际发送了什么 - 它只接受所给出的值(即它从来没有直接与请求交流)。
这还意味着你可以在没有表单甚至没有HTTP请求的情况下测试逻辑。
实际上,ASP.NET MVC会为你完成很多这方面的工作(上面的段落)...
请注意,你可以更新.Items集合 - 但这有点模糊(即它与表单无关)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接