开发者

how do I manually create POST parameters that are nested? (e.g. I'm creating the request in .Net to contact a Rails backend)

How do I manually create nested POST parameters for a http web request? I have a .NET C# client for which I'm creating a HTTP request to a Rails page. Everything is fine so far, however I've noted that the parameters I'm creating for the request (key/value pairs) are expected to be nested. I'm actually also having a hard time trying to work out in a controller before_filter how to do a "puts" on the raw request content to see how a successful request formats it.

RAILS BACKEND EXPECTATION (a successful login file, when I called from browser (not .net))

 action_controller.request.request_parameters: !map:HashWithIndifferentAccess
   commit: Save
   webfile: !map:HashWithIndifferentAccess
     path: winter
     file: &id005 !ruby/object:File
       content_type: image/jpeg
       original_path: Winter.jpg

C# Parameter Creation:

    var form = new NameValueCollection();
    form["path"] = "winter";  ==> THIS DOESN'T WORK BECAUSE I THINK IT MAY HAVE TO BE NESTED WITHIN THE "webfile" HASH

C# Routine:

    public static HttpWebResponse Upload(HttpWebRequest req, UploadFile[] files, NameValueCollection form)
    {
        List<MimePart> mimeParts = new List<MimePart>();

        try
        {
            foreach (string key in form.AllKeys)
            {
                StringMimePart part = new StringMimePart();

                part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
                part.StringData = form[key];

                mimeParts.Add(part);
            }

            int nameIndex = 0;

            foreach (UploadFile file in files)
            {
                StreamMimePart part = new StreamMimePart();

                if (string.IsNullOrEmpty(file.FieldName))
                    file.FieldN开发者_高级运维ame = "file" + nameIndex++;

                part.Headers["Content-Disposition"] = "form-data; name=\"" + file.FieldName + "\"; filename=\"" + file.FileName + "\"";
                part.Headers["Content-Type"] = file.ContentType;

                part.SetStream(file.Data);

                mimeParts.Add(part);
            }

            string boundary = "----------" + DateTime.Now.Ticks.ToString("x");

            req.ContentType = "multipart/form-data; boundary=" + boundary;
            req.Method = "POST";

            long contentLength = 0;

            byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

            foreach (MimePart part in mimeParts)
            {
                contentLength += part.GenerateHeaderFooterData(boundary);
            }

            req.ContentLength = contentLength + _footer.Length;

            byte[] buffer = new byte[8192];
            byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
            int read;

            using (Stream s = req.GetRequestStream())
            {
                foreach (MimePart part in mimeParts)
                {
                    s.Write(part.Header, 0, part.Header.Length);

                    while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
                        s.Write(buffer, 0, read);

                    part.Data.Dispose();

                    s.Write(afterFile, 0, afterFile.Length);
                }

                s.Write(_footer, 0, _footer.Length);
            }

            return (HttpWebResponse)req.GetResponse();
        }
        catch
        {
            foreach (MimePart part in mimeParts)
                if (part.Data != null)
                    part.Data.Dispose();

            throw;
        }
    }

Thanks

PS. In particular I think what I'm after is: * how does Rails serialize a nested form parameter/hash into an actual HTTP Request body, and/or * a pointer to a specific class in the Rails code base that does this (so I can have a look and then emulate within my .net client)


You're not exactly clear with what you're trying to do here. So I don't think we can correct the issue for you.

Best I can suggest is that you submit the form via the web using a tool that monitors requests, such as Firebug. It will tell you exactly what's in the HTTP request, and not what Rails interprets. You can use that information to craft the HTTP request you want.

FYI Rails uses pairs of square brackets in keys to denote nesting and arrays in parameters. Empty square brackets indicate lists, while filled square brackets indicates another level of nesting. A hash with indifferent access is a hash that has an implicit to_s call on strings and symbols for all keys used to access the hash.

Example:

When you create the form like this:

var form = new NameValueCollection();
form["user[name]"] = "EmFi";
form["user[phone_number]" = "555-555-1234";
form["user[friend_ids][]" = "7";
form["user[friend_ids][]" = "8";
form["user[address][street_number]" = "75";
form["user[address][street_name]" = "Any St.";
form["user[address][province]" = "Ontario";
form["user[address][country]" = "Candad";

then pass it to the subroutine posted in the question, this is the params hash rails will provide the controller:

params = {
  "user" => {
    "name" => "EmFi,
    "phone_number" => "555-555-1234",
    "friend_ids" => ["7","8"],
    "address" => {
      "street_number" => "75",
      "street_name" => "any St.",
      "province" => "Ontario",
      "country" => "Canada",
    }
  }
}


am sending nested map parameters in groovy

//parameters def attrs= [a:'A', m:[b:'B'],c:'C']

def http = new HTTPBuilder('http://www.websitexyz.com')

    http.request(Method.POST, ContentType.TEXT) { req ->
            send ContentType.URLENC, attrs
 // executed for all successful responses:
 response.success = { resp, reader ->
   println 'my response handler!'
   assert resp.statusLine.statusCode == 200
   println resp.statusLine
   System.out << reader // print response stream
 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜