C# Owin WebApp: Parsing POST Requests?

Viewed 10560

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!

5 Answers

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

Related