13

I try Request.Form.Set(k, v) but it's throwing exception

Collection is read-only

T.S.
  • 18,195
  • 11
  • 58
  • 78
complez
  • 7,882
  • 11
  • 48
  • 56

2 Answers2

13

This is exactly the same as modifying Request.Querystring. Both are internally complicated by private properties and what could be deemed a bug, however there are two possible solutions I'm aware of (I'll dismiss the response.redirect plan out of hand - that's terrible).

Method one is to use reflection to modify the collection directly:

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); 

Plan B, which I think lends itself better to unit testing is to avoid dealing with the collection directly and instead pass it as a NameValueCollection to any method you want to handle it, shallow copying whatever you need out of it. I've used this myself to mock web requests.

Edit: Marc Gravell gave more eloquent reasons for plan B

T.S.
  • 18,195
  • 11
  • 58
  • 78
annakata
  • 74,572
  • 17
  • 113
  • 180
  • 2
    Manipulating private stuff in this manner is by no means a suggested thing and should be avoided as much as possible (~= at all costs). After all they are made private for a reason. You'll rely on a specific version of a library. Any change in the underlying implementation might break your app. – Mehrdad Afshari Nov 30 '08 at 18:13
  • And you'll see I advocate plan B – annakata Feb 04 '09 at 13:49
  • Plan A missed something detail. I think it not right way. You can test by yourself. – Joe.wang Aug 27 '12 at 12:20
  • Don't use "Plan A". It doesn't work with Mono and even if that might be considered as "irrelevant", it still shows that there is something really dirty going on with that code and just shouldn't be done. – Tobias81 Oct 24 '14 at 07:38
1

The form is a representation of what the client sent in the request. What is it you want to do? Personally, I would try to separate the "read the form" code from the "do something with the values" code - that way, you can do any pre-processing early on (when reading from the form), and none of the later code needs to know about what was actually sent - it just takes the values given to it (i.e. it never talks to the request directly).

It also means you can test your logic without the need for a form, or even an http-request at all.

Actually, ASP.NET MVC will do a lot of this (the above paragraph) for you...

Note that you can update the .Items collection - but this is a bit more vague (i.e. it doesn't relate specifically to the form).

Myobis
  • 1,347
  • 16
  • 27
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900