我想在C#控制台应用程序中解析HTTP POST请求方面的一些帮助。该应用程序使用Owin运行“网络服务器”。该应用程序的详细信息可用here,相关代码的当前“稳定版本”为here。
我正在扩展上述应用程序以通过Web UI启用配置。例如,app当前报告了大量参数。我希望最终用户能够选择通过网络报告哪些参数。为此,我对上面的代码做了一些修改:
using Microsoft.Owin;
using Owin;
.........
[assembly: OwinStartup(typeof(SensorMonHTTP.WebIntf))]
.........
.........
namespace SensorMonHTTP
{
...
public class WebIntf
{
public void Configuration(IAppBuilder app)
{
app.Run(context =>
{
var ConfigPath = new Microsoft.Owin.PathString("/config");
var ConfigApplyPath = new Microsoft.Owin.PathString("/apply_config");
var SensorPath = new Microsoft.Owin.PathString("/");
if (context.Request.Path == SensorPath)
{
return context.Response.WriteAsync(GetSensorInfo());
/* Returns JSON string with sensor information */
}
else if (context.Request.Path == ConfigPath)
{
/* Generate HTML dynamically to list out available sensor
information with checkboxes using Dynatree: Tree3 under
'Checkbox & Select' along with code to do POST under
'Embed in forms' in
http://wwwendt.de/tech/dynatree/doc/samples.html */
/* Final segment of generated HTML is as below:
<script>
.....
$("form").submit(function() {
var formData = $(this).serializeArray();
var tree = $("#tree3").dynatree("getTree");
formData = formData.concat(tree.serializeArray());
// alert("POST this:\n" + jQuery.param(formData));
// -- This gave the expected string in an alert when testing out
$.post("apply_config", formData);
return true ;
});
......
</script></head>
<body>
<form action="apply_config" method="POST">
<input type="submit" value="Log Selected Parameters">
<div id="tree3" name="selNodes"></div>
</body>
</html>
End of generated HTML code */
}
else if (context.Request.Path == ConfigApplyPath)
{
/* I want to access and parse the POST data here */
/* Tried looking into context.Request.Body as a MemoryStream,
but not getting any data in it. */
}
}
}
........
}
任何人都可以帮助我了解如何在上面的代码结构中访问POST数据吗?
提前致谢!
答案 0 :(得分:9)
由于数据以KeyValuePair格式返回,您可以将其转换为IEnumerable,如下所示:
var formData = await context.Request.ReadFormAsync() as IEnumerable<KeyValuePair<string, string[]>>;
//现在你有了可以查询的列表
var formElementValue = formData.FirstOrDefault(x => x.Key == "NameOfYourHtmlFormElement").Value[0]);
答案 1 :(得分:4)
您可以使用IOwinRequest对象上的ReadFormAsync()实用程序来读取/解析表单参数。
public void Configuration(IAppBuilder app)
{
app.Run(async context =>
{
//IF your request method is 'POST' you can use ReadFormAsync() over request to read the form
//parameters
var formData = await context.Request.ReadFormAsync();
//Do the necessary operation here.
await context.Response.WriteAsync("Hello");
});
}
答案 2 :(得分:1)
要为每种内容类型提取body参数,您可以使用以下方法:
public async static Task<IDictionary<string, string>> GetBodyParameters(this IOwinRequest request)
{
var dictionary = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
if (request.ContentType != "application/json")
{
var formCollectionTask = await request.ReadFormAsync();
foreach (var pair in formCollectionTask)
{
var value = GetJoinedValue(pair.Value);
dictionary.Add(pair.Key, value);
}
}
else
{
using (var stream = new MemoryStream())
{
byte[] buffer = new byte[2048]; // read in chunks of 2KB
int bytesRead;
while ((bytesRead = request.Body.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, bytesRead);
}
var result = Encoding.UTF8.GetString(stream.ToArray());
// TODO: do something with the result
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
foreach(var pair in dict)
{
string value = (pair.Value is string) ? Convert.ToString(pair.Value) : JsonConvert.SerializeObject(pair.Value);
dictionary.Add(pair.Key, value);
}
}
}
return dictionary;
}
private static string GetJoinedValue(string[] value)
{
if (value != null)
return string.Join(",", value);
return null;
}
答案 3 :(得分:0)
context.Request.Body是获取POST值的正确位置,但您需要在要访问的表单元素上包含name属性。如果没有name属性,一切都会被忽略,虽然有可能,但我无法找到访问原始请求的方法 - 之前从未使用过Owin。
if (context.Request.Path == ConfigPath)
{
StringBuilder sb = new StringBuilder();
sb.Append("<html><head></head><body><form action=\"apply_config\" method=\"post\">");
sb.Append("<input type=\"submit\" value=\"Log Selected Parameters\">");
sb.Append("<input type=\"text\" value=\"helloworld\" name=\"test\"></input>");
sb.Append("</body>");
sb.Append("</html>");
return context.Response.WriteAsync(sb.ToString());
}
else if (context.Request.Path == ConfigApplyPath)
{
/* I want to access and parse the POST data here */
/* Tried looking into context.Request.Body as a MemoryStream,
but not getting any data in it. */
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[8000];
int read = 0;
read = context.Request.Body.Read(buffer, 0, buffer.Length);
while (read > 0)
{
sb.Append(Encoding.UTF8.GetString(buffer));
buffer = new byte[8000];
read = context.Request.Body.Read(buffer, 0, buffer.Length);
}
return context.Response.WriteAsync(sb.ToString());
}
else
{
return context.Response.WriteAsync(GetSensorInfo());
/* Returns JSON string with sensor information */
}
答案 4 :(得分:0)
以下工作,诀窍是重置流的位置。
context.Request.Body.Position = 0;
string content = new StreamReader(context.Request.Body).ReadToEnd();