C# Owin WebApp: Parsing POST Requests?

10,465

Solution 1

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

Solution 2

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

Solution 3

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

Share:
10,465
Ganesh_AT
Author by

Ganesh_AT

Updated on June 14, 2022

Comments

  • Ganesh_AT
    Ganesh_AT almost 2 years

    I would like some help on parsing HTTP POST requests in a C# console application. The app runs a 'web-server' using Owin. Details of the application are available here and the current 'stable version' of the relevant code is here.

    I am extending the above application to enable configuration through the web UI. For example, the app currently reports a large number of parameters. I would like the end-user to be able to select which parameters get reported over the network. Towards this, I made some modifications to the code above:

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

    Can anyone help me with how the POST data can be accessed in the above code structure?

    Thanks in advance!

  • Ganesh_AT
    Ganesh_AT over 10 years
    Andrew, Thanks for the response. It turned out that I had a problem in modifying the JavaScript code from the Dynatree example: particularly, the form submit procedure apparently had to return 'false' for the form data to be sent over correctly. I have since resolved the issue.