C# Owin WebApp: Parsing POST Requests?

不问归期 提交于 2019-12-04 10:13:27
bilmuhfk

Since the data returns in KeyValuePair format you can cast it as IEnumerable which looks something like the following:

var formData = await context.Request.ReadFormAsync() as IEnumerable<KeyValuePair<string, string[]>>;

//now you have the list that you can query against

var formElementValue = formData.FirstOrDefault(x => x.Key == "NameOfYourHtmlFormElement").Value[0]);

You can use the ReadFormAsync() utility on the IOwinRequest object to read/parse the form parameters.

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

To extract the body Parameters for each content type you can use a method like this:

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

References: Most efficient way of reading data from a stream

The context.Request.Body is the right place to get POST values, but you need to include a name attribute on the form elements that you want to access. Without the name attribute everything is ignored, and I wasn't able to find a way to access the raw request although it might be possible - never used Owin before.

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 */
}

The following works, the trick is to reset the position of the stream.

context.Request.Body.Position = 0;
string content = new StreamReader(context.Request.Body).ReadToEnd();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!