简体   繁体   中英

Using C#, how do I conditionally isolate Request.Params when there is a File in the request stream?

I feel like I am missing something obvious here. I have the following code that executes when a user submits a checkout form online:

Stream body = Request.InputStream;
Encoding encoding = Request.ContentEncoding;
StreamReader reader = new StreamReader(body, encoding);
string json = reader.ReadToEnd();

dynamic order = JObject.Parse(json);

This works great and it allows me to then easily reference all of the properties in the stream simply by referencing the order object. (eg order.CustomerName ).

The Problem

My client has added the requirement that the user may upload a file such as a purchase order. I have added the code to upload the file without issue, but now the code block I posted above barfs if there is a file in the InputStream . Specifically, the error is "Input string '------' is not a valid number" which is thrown here:

dynamic order = JObject.Parse(json);

So, I assume that I need to somehow isolate Request.Params when there is a file in the InputStream and then run that through the code block above, but I am having a hard time getting down that road.

Any pointers, hints, or advice is welcome. Thanks.

Have you considered sending the JSON and file up as multipart/form-data , the same as you would if you were POSTing a file upload from an HTML form?

That way you would have what looks to the server as 1 or more HttpPostedFile objects in Request.Files (1 for the JSON, 1 each more for each file). Each of those HttpPostedFile objects would have its own InputStream . That for the first "file" can be used for body in code as per your question, and will work pretty much as it does now, while the other HttpPostedFile objects can be used much as is normal for file uploads.

Here is the solution I ultimately came up with thanks to the help of this Stack Overflow question :

If the POST included an uploaded file, then my code for handling the parameters changed from this :

dynamic order = new ExpandoObject();

...

Stream body = Request.InputStream;
Encoding encoding = Request.ContentEncoding;
StreamReader reader = new StreamReader(body, encoding);
string json = reader.ReadToEnd();

dynamic order = JObject.Parse(json);

To this :

dynamic order = new ExpandoObject();

...

 if (hasFile)
        {
            attachment = HttpContext.Current.Request.Files[0];

            var dict = NvcToDictionary(HttpContext.Current.Request.Form, false);
            foreach (var item in dict)
            {
                var _json = item.Value.ToString();
                ((IDictionary<string, object>)order)[item.Key] = JObject.Parse(_json);
            }    
        }

Note the use of the ExpandoObject type and the ((IDictionary<string, object>)order) part. This was necessary so that I could set the order variable dynamically.

Now that I look at this with a fresh brain, I see that I could have probably used a common approach--regardless of the presence of a file--for casting the form params to a dynamic object (using the hasFile logic). So if you are in need of a solution for the same problem, maybe just do that.

Here is the NvcToDictionary helper method from the related question:

static Dictionary<string, object> NvcToDictionary(NameValueCollection nvc, bool handleMultipleValuesPerKey)
    {
        var result = new Dictionary<string, object>();
        foreach (string key in nvc.Keys)
        {
            if (handleMultipleValuesPerKey)
            {
                string[] values = nvc.GetValues(key);
                if (values.Length == 1)
                {
                    result.Add(key, values[0]);
                }
                else
                {
                    result.Add(key, values);
                }
            }
            else
            {
                result.Add(key, nvc[key]);
            }
        }

        return result;
    }

Cheers!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM