[英]How to modify HttpContext.Request.Form in asp.net core
I have an HttpContext.Request object that has data in the Form that is wrong and I want to fix it up and send the correct HttpContext on its way.我有一个 HttpContext.Request 对象,它的表单中的数据是错误的,我想修复它并在途中发送正确的 HttpContext。 HttpContext.Request.Form is readonly, but if it wasn't I would have simply done the following;
HttpContext.Request.Form 是只读的,但如果不是,我会简单地执行以下操作; HttpContext.Request.Form["a"] = "the correct value for a";
HttpContext.Request.Form["a"] = "a 的正确值";
So, where is the best place in the pipeline to do this.那么,在管道中执行此操作的最佳位置在哪里。 Is it possible to make the HttpContext.Request.Form write accessable via reflection?
是否可以通过反射使 HttpContext.Request.Form 可写访问?
This was easier than I thought.这比我想象的要容易。 I am doing this in my middleware which is there to correct bad form data that came in.
我在我的中间件中执行此操作,以纠正传入的错误表单数据。
public async Task Invoke(HttpContext context)
{
....
NameValueCollection fcnvc = context.Request.Form.AsNameValueCollection();
fcnvc.Set("a", "the correct value of a");
fcnvc.Set("b", "a value the client forgot to post");
Dictionary<string, StringValues> dictValues = new Dictionary<string, StringValues>();
foreach (var key in fcnvc.AllKeys)
{
dictValues.Add(key, fcnvc.Get(key));
}
var fc = new FormCollection(dictValues);
context.Request.Form = fc;
....
await _next.Invoke(context);
}
Interestingly the FormCollection is readonly, but the HttpContext.Request object is not thus allowing me to replace the entire Form.有趣的是,FormCollection 是只读的,但 HttpContext.Request 对象不允许我替换整个表单。
AsNameValueCollection is inside of IdentityServer4.dll. AsNameValueCollection 在 IdentityServer4.dll 中。
public static class IReadableStringCollectionExtensions
{
[DebuggerStepThrough]
public static NameValueCollection AsNameValueCollection(this IDictionary<string, StringValues> collection)
{
NameValueCollection values = new NameValueCollection();
foreach (KeyValuePair<string, StringValues> pair in collection)
{
string introduced3 = pair.get_Key();
values.Add(introduced3, Enumerable.First<string>(pair.get_Value()));
}
return values;
}
[DebuggerStepThrough]
public static NameValueCollection AsNameValueCollection(this IEnumerable<KeyValuePair<string, StringValues>> collection)
{
NameValueCollection values = new NameValueCollection();
foreach (KeyValuePair<string, StringValues> pair in collection)
{
string introduced3 = pair.get_Key();
values.Add(introduced3, Enumerable.First<string>(pair.get_Value()));
}
return values;
}
}
A bit complex but shorter solution
有点复杂但更短的解决方案
var collection = HttpContext.Request.Form;
var propInfo = collection.GetType().GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
propInfo.SetValue(collection, false, new object[]{});
collection.Remove("a");
collection.Add("a", "the correct value for a");
System.Diagnostics.Debug.Write(HttpContext.Request["a"]); // the correct value for a
Enjoy!
享受!
Here's a .NET Core/5 solution that worked for me without using the Identity Server package.这是一个 .NET Core/5 解决方案,它在不使用 Identity Server 包的情况下对我有用。
Basically you build a new dictionary of type <string, StringValues>
out of the existing form collection, modify the values in the dictionary how you want, then create a new FormCollection
from that dictionary and set it to context.Request.Form
.基本上,您从现有的表单集合中构建一个
<string, StringValues>
类型的新字典,根据需要修改字典中的值,然后从该字典创建一个新的FormCollection
并将其设置为context.Request.Form
。 The important thing to remember is that the value which is of type StringValues is just an array of strings!要记住的重要一点是,StringValues 类型的值只是一个字符串数组!
This example demonstrates me removing a "client_id" field from the request form.此示例演示了我从请求表单中删除“client_id”字段。
var formDictionary = new Dictionary<string, StringValues>();
var form = context.Request.Form;
foreach (var key in form.Keys)
{
// Only add if key is NOT client_id
if (key != "client_id")
{
form.TryGetValue(key, out StringValues formValues);
formDictionary.Add(key, formValues);
}
}
FormCollection formCollection = new FormCollection(formDictionary);
context.Request.Form = formCollection;
Here is another example of me changing the "client_id" field to "NewValue"这是我将“client_id”字段更改为“NewValue”的另一个示例
var formDictionary = new Dictionary<string, StringValues>();
var form = context.Request.Form;
foreach (var key in form.Keys)
{
form.TryGetValue(key, out StringValues formValues);
// Change client_id value to "NewValue"
if (key == "client_id")
{
formValues = new string[] { "NewValue" };
}
formDictionary.Add(key, formValues);
}
FormCollection formCollection = new FormCollection(formDictionary);
context.Request.Form = formCollection;
I personally prefer to use an extended method to do this.我个人更喜欢使用扩展方法来做到这一点。
public static IFormCollection PushToForm(this IFormCollection form, Dictionary<string, StringValues> data)
{
var formDictionary = new Dictionary<string, StringValues>();
foreach (var k in form.Keys)
{
form.TryGetValue(k, out StringValues v);
formDictionary.Add(k, v);
}
foreach (var x in data) formDictionary.Add(x.Key, x.Value);
return new FormCollection(formDictionary);
}
Example:例子:
Request.Form = Request.Form.PushToForm(new Dictionary<string, StringValues>()
{
{ "key1", new string[] { "value1" } },
{ "key2", new string[] { "value2" } },
{ "key3", new string[] { "value3" } },
...
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.