Search Unity

How to post JSON in body?

Discussion in 'Scripting' started by Patico, Mar 9, 2016.

  1. Patico

    Patico

    Joined:
    May 21, 2013
    Posts:
    886
    I'm working on the client code for my RESTfull service, and wondering is there any way to send POST request using UnityWebRequest.Post with json data in body instead of WWWForm?

    I made a call like this:
    Code (csharp):
    1. var bodyData = "{ 'test': 'value' }";
    2. using( UnityWebRequest req = UnityWebRequest.Post( url, bodyData )){
    3.  
    4.   yield return www.Send();
    5.   ...
    6. }
    But server returns a 400 error, meaning that request was not correct.
    By the way, maybe some one also know a way to debug HTTP calls of UnityWebRequest? I tries to catch them with Fiddler but without any success.
     
  2. Patico

    Patico

    Joined:
    May 21, 2013
    Posts:
    886
  3. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    974
    Based on the documentation, I'm not sure why your code compiles. Looks like there are these options when building a WWW object:
    • public WWW(string url);
    • public WWW(string url, WWWForm form);
    • public WWW(string url, byte[] postData);
    • public WWW(string url, byte[] postData, Hashtable headers);
    • public WWW(string url, byte[] postData, Dictionary<string,string> headers);
    However, you seem to be using a non-existent
    • public WWW(string url, string content);
    constructor. My only guess is that, either your code doesn't compile, or WWWForm has an implicit conversion from string, which probably doesn't produce what you expect.

    Having never done this before, my suggestion is to convert your string into a byte[] before passing to the WWW class. You can do that with one of the Encodings, though you probably just want UTF8.

    Code (csharp):
    1. var bodyData = "{ 'test': 'value' }";
    2. var postData = System.Text.Encoding.UTF8.GetBytes(bodyData);
    3. using( UnityWebRequest req = UnityWebRequest.Post( url, postData)){
    4.   yield return www.Send();
    5.   // ...
    6. }
    Of course, to really be able to figure out what's going on, this is a hurdle you'll need to get over. Here's some suggestions:
    • Make sure you are able to capture http traffic from other processes
    • If you are passing data over https, you'll need to install the Fiddler certificate
    • Try capturing traffic form a desktop version of your game rather than a web or emulator version
     
    stacklikemind and Patico like this.
  4. Patico

    Patico

    Joined:
    May 21, 2013
    Posts:
    886
    Thank you, @eisenpony for so detailed answer!
     
  5. KGC

    KGC

    Joined:
    Oct 2, 2014
    Posts:
    12
    For anyone coming here in 2019 using Unity 2018 (I'm on 2018.3.10f1), this answer is no longer correct since Unity has changed the API for UnityWebRequest.Post().

    The way i solved it was not using the .Post() method, but instead configure it all myself. The reason why i need to do so, is that Unity automatically URL encodes your request body string, without you having an easy way to disable that, see the documentation:

    Code (CSharp):
    1. //
    2. // Summary:
    3. //     Creates a UnityWebRequest configured to send form data to a server via HTTP POST.
    4. //
    5. // Parameters:
    6. //   uri:
    7. //     The target URI to which form data will be transmitted.
    8. //
    9. //   postData:
    10. //     Form body data. Will be URLEncoded prior to transmission.
    11. //
    12. // Returns:
    13. //     A UnityWebRequest configured to send form data to uri via POST.
    14. public static UnityWebRequest Post(string uri, string postData);

    Heres my solution:

    Code (CSharp):
    1. public UnityWebRequest CreateApiGetRequest(string actionUrl, object body = null)
    2. {
    3.     return CreateApiRequest(BaseUrl + actionUrl, UnityWebRequest.kHttpVerbGET, body);
    4. }
    5.  
    6. public UnityWebRequest CreateApiPostRequest(string actionUrl, object body = null)
    7. {
    8.     return CreateApiRequest(BaseUrl + actionUrl, UnityWebRequest.kHttpVerbPOST, body);
    9. }
    10.  
    11. UnityWebRequest CreateApiRequest(string url, string method, object body)
    12. {
    13.     string bodyString = null;
    14.     if (body is string)
    15.     {
    16.         bodyString = (string)body;
    17.     }
    18.     else if (body != null)
    19.     {
    20.         bodyString = JsonUtility.ToJson(body);
    21.     }
    22.  
    23.     var request = new UnityWebRequest();
    24.     request.url = url;
    25.     request.method = method;
    26.     request.downloadHandler = new DownloadHandlerBuffer();
    27.     request.uploadHandler = new UploadHandlerRaw(string.IsNullOrEmpty(bodyString) ? null : Encoding.UTF8.GetBytes(bodyString));
    28.     request.SetRequestHeader("Accept", "application/json");
    29.     request.SetRequestHeader("Content-Type", "application/json");
    30.     request.timeout = 60;
    31.     return request;
    32. }

    Usage:

    Code (CSharp):
    1. var request = webApi.CreateApiGetRequest("/test"); // Get request with blank request body
    2.  
    3. [Serializable]
    4. public class ApiAuthenticateRequest
    5. {
    6.     public string Email;
    7.     public string Password;
    8. }
    9.  
    10. var request = webApi.CreateApiPostRequest("/auth", new ApiAuthenticateRequest { Email = "email@example.com", Password = "correcthorsebatterystaple" } ); // Post request with JSON request body
     
  6. megamil3d

    megamil3d

    Joined:
    Oct 14, 2020
    Posts:
    1
    Thank you, test 2020 december OK

    my code:

    Code (CSharp):
    1.  
    2. //Using
    3. object form = new LoginEntity { email = inputEmail.text, password = inputPass.text }; // Post request with JSON request body
    4.  
    5. StartCoroutine(RequestWebService(
    6. Endpoints.POST,
    7. Endpoints.Login,
    8. form,
    9. null,
    10. alertPrefabObj
    11. ));
    12.  
    13.  
    Code (CSharp):
    1.  
    2. IEnumerator RequestWebService(string method, string endpoint, object body, string bearerToken, AlertScript alertPrefabObj)
    3. {
    4.  
    5. string getDataUrl = Constants.URL_BASE + endpoint;
    6. Debug.Log("---------------- URL ----------------");
    7. Debug.Log(getDataUrl);
    8.  
    9. var webData = new UnityWebRequest();
    10. webData.url = getDataUrl;
    11. webData.method = method;
    12. webData.downloadHandler = new DownloadHandlerBuffer();
    13. webData.uploadHandler = new UploadHandlerRaw(string.IsNullOrEmpty(JsonUtility.ToJson(body)) ? null : Encoding.UTF8.GetBytes(JsonUtility.ToJson(body)));
    14. webData.timeout = 60;
    15.  
    16. Debug.Log("---------------- Header ----------------");
    17. webData.SetRequestHeader("Accept", "application/json");
    18. webData.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
    19. webData.SetRequestHeader("Api-Token", Constants.API_TOKEN);
    20. if(bearerToken != null){
    21. webData.SetRequestHeader("Authorization", "Bearer " + bearerToken);
    22. }
    23.  
    24. yield return webData.SendWebRequest();
    25. if (webData.isNetworkError)
    26. {
    27. Debug.Log("---------------- ERROR ----------------");
    28. Debug.Log(webData.error);
    29. }
    30. else
    31. {
    32. if (webData.isDone)
    33. {
    34. Debug.Log("---------------- Response Raw ----------------");
    35. Debug.Log(Encoding.UTF8.GetString(webData.downloadHandler.data));
    36. JSONNode jsonData = JSON.Parse(Encoding.UTF8.GetString(webData.downloadHandler.data));
    37.  
    38. if (jsonData == null)
    39. {
    40. Debug.Log("---------------- NO DATA ----------------");
    41. }
    42. else
    43. {
    44. Debug.Log("---------------- JSON DATA ----------------");
    45. Debug.Log(jsonData);
    46.  
    47. if(jsonData["status"].ToString().Equals("1")){
    48. goToSceneTabbar();
    49. } else {
    50. alertPrefabObj.setErrorMessage(jsonData["msg"]);
    51. alertPrefabObj.transform.SetParent (GameObject.FindGameObjectWithTag("CanvasHome").transform, false);
    52. }
    53.  
    54. }
    55. }
    56. }
    57. }
    58.