Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

UnityWebRequest.Post(url, jsonData) sending broken Json

Discussion in 'Connected Games' started by Olly, Jul 2, 2016.

  1. Olly

    Olly

    Joined:
    Jun 19, 2014
    Posts:
    20
    I'm doing the following: (Don't worry it will be over HTTPS)

    Code (csharp):
    1.  UnityWebRequest.Post(url,jsonData)

    The json data is as follows:
    Code (csharp):
    1.  {"username":"some username","password":"some password"}
    The data is actually of type JsonObject but I've tried passing it as a string too.

    When using PostMan tool in Chrome and sending this data it was processing correctly.

    When sending via Unity I get additional data that fails Json linter:

    Code (csharp):
    1.  { '{"translationKey":"","username":"","password":""}': '' }
    I have tried manually stripping the code; but I'd rather be sending safe json to begin with.

    I'm using Express with NodeJS.

    Can someone tell me what I'm doing wrong?


    ** Edit **

    I'm using JsonUtility.ToJson(jsonData) to parse the data

    Example of Json class:
    Code (csharp):
    1.  
    2. public class JsonObjectNewUser : JsonObjectBase {
    3.  
    4.     public string username;
    5.     public string password;
    6.  
    7.     public JsonObjectNewUser(string username, string password) {
    8.         this.username = username;
    9.         this.password = password;
    10.     }
    11. }
    12.  
    BaseJson
    Code (csharp):
    1.  
    2. [System.Serializable]
    3. publicclassJsonObjectBase{
    4.     publicstringtranslationKey="";
    5. }
    6.  
    Logging JsonUtility.ToJson(jsonObject) produces the correct json:
    Code (csharp):
    1.  
    2. {
    3.     "translationKey": "",
    4.     "username": "",
    5.     "password": ""
    6. }
    7.  
    So something is being added in UnityWebRequest.Post..
     
    Last edited: Jul 2, 2016
  2. Olly

    Olly

    Joined:
    Jun 19, 2014
    Posts:
    20
    I figured this out; use Put request and make sure the content header is set.

    Example
    Code (csharp):
    1.  
    2. var jsonString = JsonUtility.ToJson(jsonData) ?? "";
    3. UnityWebRequest request = UnityWebRequest.Put(url, jsonString);
    4. request.SetRequestHeader("Content-Type", "application/json");
    5. yield return request.Send();
    6.  
     
    Armamedia likes this.
  3. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    280
    I stumbled upon this same issue. I can't get the POST method to work with JSON, but I can get it to work with PUT.
     
    StoneIron-H-D likes this.
  4. Apparaten_

    Apparaten_

    Joined:
    Jul 9, 2013
    Posts:
    44
    I dont have any trouble with post, what version of unity are you using?

    Im using the wwwform for sending data to server. I only use Jsonutility when i get data from my server.
     
  5. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    280
    I can also use POST with WWWForm. It is using POST where data is JSON formatted and Content-Type is set to application/json.
     
  6. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    UnityWebRequest is a very poor implementation of an HTTP client.

    This might be your problem, depending on what is consuming your request: For some reason UnityWebRequest applies URL encoding to POST message payloads. URL encoding the payload is an ASP.NET webform thing. It is not part of the HTML standard (and if it were, it still shouldn't matter to an HTTP client), and it certainly is not part of the HTTP standard.

    To get an unmangled-POST through, create UnityWebRequest as a PUT, then in your own code change the Method property to POST after the fact.

    Also note that if your RESTful API requires message payloads on GET requests (rare, but it happens, typically as part of sending complex search parameters) you'll either have to change the API or find an alternative to UnityWebRequest. It will simply discard the message body if you change the method to GET. (Note I haven't confirmed it's the GET that discards the body; I also set Content-Type and that may trigger it too, I stopped caring about the specifics after I realized it was blindly throwing away my data.)

    Error handling is also a mess. There is no comprehensive list of the errors the class itself can return and they're just raw text strings. Server response is available strictly as the numeric response status code (annoyingly expressed as longs which means you have to remember to test against "200L" for OK, for example), and UnityWebRequest does not expose the response status description text, which means it throws away potentially useful error messages.

    Oh yeah, it also won't allow an empty message body on a POST or PUT operation, which is also stupid and not to HTTP spec.

    There are open feedback items for most of these. Upvotes would be appreciated. I don't have much hope they'll fix it, though. In another thread a Unity dev started to argue about these, then bailed on the thread entirely. Other threads about these issues have been ignored (or maybe were not noticed in all the other traffic, no way to know for sure).

    Right now I'm pondering whether to break my REST API to accomodate this mess, or ditch UnityWebRequest for some as-yet-unknown alternative, but I need the coroutine/yield async model and I haven't dug into doing that DIY yet. Extremely frustrating.
     
    Last edited: Jul 22, 2016
  7. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    179
    Today I used that code and now it is working perfectly:

    Code (CSharp):
    1.     IEnumerator Post(string url, string bodyJsonString)
    2.     {
    3.         var request = new UnityWebRequest(url, "POST");
    4.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    5.         request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
    6.         request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
    7.         request.SetRequestHeader("Content-Type", "application/json");
    8.  
    9.         yield return request.Send();
    10.  
    11.         Debug.Log("Status Code: " + request.responseCode);
    12.     }
    Source: http://qiita.com/mattak@github/items/d01926bc57f8ab1f569a
     
    shroeder, yusyus, Liut2018 and 6 others like this.
  8. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    280
    I am currently using UnityWebRequest for our REST api, and I find it easy to use, and haven't stumbled upon that many issues. Could you pleas link to the open feedback requests?
     
  9. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    267
    I am using UnityWebRequest example from here: https://docs.unity3d.com/Manual/UnityWebRequest-SendingForm.html
    using our https url and although I get upload completed there server receives nothing.

    I also note from that site that webform is legacy and UnityWebRequest is the 'new' way of doing it...but not if it does not work?
     
  10. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    179
    @elpuerco63,
    Have you tried use this?
     
    fangyan67 likes this.
  11. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    267
  12. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    179
  13. MrSaoish

    MrSaoish

    Joined:
    Oct 1, 2016
    Posts:
    20
    I believe it required a php on http server in order to use UnityWebRequest.Post() or UnityWebRequest.Put successfully?
    I'm trying to use UnityWebRequest.Put to upload player data in jason to http server and overwrite its .txt but I'm very new to this category and having 0 experience on php scripting, does anyone have some reference .php codes I could learned from?
     
  14. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    179
    First of all, you need to learn how to code a "PHP Rest API" system that will receive data as Json and later manage the data to write in your .txt file. But maybe it will be better if instead of a .txt file, you save the data in a MySQL database.

    Just search for "PHP Rest API" tutorials and you will learn it after some time of study.

    You can use a good tool to test your PHP system before code in Unity:
    https://www.getpostman.com/apps

    After your PHP system is done, you can go to Unity and implement your "UnityWebRequest.Post".
     
    petrapparent likes this.
  15. JanouschScanblue

    JanouschScanblue

    Joined:
    May 31, 2017
    Posts:
    1
    Worked like a charm for me.
    This is how my JsonString looked like:
    "{
    'email': '*****@test.de',

    'password': '*****'
    }"
     
  16. disny1234

    disny1234

    Joined:
    Sep 21, 2014
    Posts:
    15
    I want to send some video data to servers and want to show upload progress in android using unity web request
    This html code is working, URL is working, please give me some example to achieve in unity android

    <html>
    <body>
    <form method="post" action="http://139.59.20.91/uploadVideos.php" enctype="multipart/form-data">

    Video : <input type="file" name="course_video"><br>
    <br>

    <input type="submit" value="Submit"><br>
    </form>
    </body>
    </html>
     
  17. heru_

    heru_

    Joined:
    Jun 7, 2017
    Posts:
    2
    Thanks, you've save my time
     
  18. tbriley

    tbriley

    Joined:
    Sep 10, 2013
    Posts:
    35
    this should be starred / stickied / favorited everywhere - headache cured. will keep the other bits of your reply in mind as well, cheers!
     
  19. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    The other alternative is to manually encode your JSON string to byte array and feed that.
     
  20. Finer_Games

    Finer_Games

    Joined:
    Nov 21, 2014
    Posts:
    19
    Would there be a way to make this work, if we needed to provide image data as a base64 string?
     
  21. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    The UploadHandlerBuffer takes byte array and send it as is. When using higher level functions byte array is passed directly to UploadHandlerBuffer, while anything else is transformed into byte array.
    So, if you need to send data encoded in specific form, encode it yourself and produce byte array.
     
  22. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    Is there anyway to set multiple headers using SetRequestHeaders ?
    I need to give ("Content-Type", "application/json") and ("Authorization", token). I've been searching and trying for hours but I can't find a way to do it using UnityWebRequest
     
  23. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    If keys are different, call SetRequestHeader() multiple times.
    I think what you can't do is have multiple headers with the same key, but in such cases you should be able to have only one header and put different values using comma as a separator.
     
  24. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    Using the this example code, do I code like this?

    1. IEnumerator Post(string url, string bodyJsonString)
    2. {
    3. var request = new UnityWebRequest(url, "POST");
    4. byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    5. request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
    6. request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
    7. request.SetRequestHeader("Content-Type", "application/json");
    8. request.SetRequestHeader("Authorization", "my_token");
    1. yield return request.Send();

    2. Debug.Log("Status Code: " + request.responseCode);
    3. }
     
  25. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    Yes. The casts in lines 5 and 6 are redundant, but not an error. And I recommend checking request.isError after request is completed.
     
  26. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    I see.Thank you!
    Then if I have more headers, I'll just add request.SetHeader more right?
     
  27. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    Yes, you can add as many headers as you want. Only I think it will replace header if you add the second header with the same key.
     
  28. arufolo

    arufolo

    Joined:
    Mar 5, 2013
    Posts:
    2
    You're a life saver man!!!

    www = UnityWebRequest.Put(url, bodyJSON);
    www.method = "POST";

    This was the only way I could get a POST request to work with a JSON body.
    Really poorly implemented HTTP Client on Unity's part.
     
  29. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    You use it not the way it is designed to be used.
    UnityWebRequest.Post(string, string) assumes HTTP form for second argument. If you want to send it raw, encode it to bytes (Encoding.UTF8.GetBytes(string), this is what Put does under the hood) and use UnityWebRequest.Post(string, byte[]).
     
  30. AMNOD

    AMNOD

    Joined:
    Oct 19, 2014
    Posts:
    9
    Thanks A LOTTTTT !!!
     
    marllon_alfaebeto likes this.
  31. Saulius

    Saulius

    Joined:
    Aug 10, 2010
    Posts:
    12
    I had similar problem. Everything worked on local xampp server and some other free hosting server. But when I use paid hosting I began to get empty body values. Nothing helped until I installed Wireshark and compared request sent from POSTMAN and Unity, and found out that unity had chunked transfer on by default and that web server didn't liked that for some reason.
    So setting webRequest.chunkedTransfer = false; solved it. Just in case someone will have such a problem, give a try to this solution.
     
  32. raincrowgames

    raincrowgames

    Joined:
    Jul 17, 2015
    Posts:
    1
    I know this is an old post but THANK YOU! you are lifesaver!
     
  33. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    This code works great but for some reason it didn't work with Hololens. It give me "Generic/Unknown Http error"
     
  34. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    This error means that communication with the server was successful, but server responded with HTTP error. The isHttpError property should be true on UnityWebRequest and responseCode should give the exact cause.
    One common reason for this to happen is when server does not support chunked transfer, which is what UnityWebRequest uses by default. Try setting chunkedTransfer property to false.
     
  35. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    I tested it. It didn't work but shouldn't it respond me with that error while I'm in editor mode and also in Hololens?
    Currently, I only receive this error only when I deploy to Hololens but not in editor.
     
  36. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    The response should be the same for the identical request. Different response indicates that the request was somehow different. Check the response code, that can give some clue in what way it was different.
     
  37. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    This is kinda weird. In unity editor it give me 200 but in hololens it give me 500.
     
  38. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    You need to looks at network traffic then to see what data is being transmitted.
     
  39. scarffy

    scarffy

    Joined:
    Jan 15, 2013
    Posts:
    18
    I looked at network traffic and what data is being transmitted. It seems like JsonUtility doesn't work in Hololens for some reason. I'm using newtonsoft.Json and just like that, it's working fine. Thanks @Aurimas-Cernius for the direction you gave me.
     
    Last edited: Jan 19, 2018
  40. Kraato5

    Kraato5

    Joined:
    Mar 11, 2015
    Posts:
    2
    God bless you, mate! God bless you!
     
    jvalencia likes this.
  41. fangyan67

    fangyan67

    Joined:
    Feb 25, 2014
    Posts:
    4
    Thank you thank you, It's so useful.
     
  42. Romaleks360

    Romaleks360

    Joined:
    Sep 9, 2017
    Posts:
    3
    How's that possible if UnityWebRequest.Post(string, string) accepts only strings as arguments?
     
  43. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    1,813
    There are multiple overloads of this methods accepting different arguments.