Can you post a json string as a body in Unity?

I’m trying to post a json string as the body of a UnityWebRequest but it just fails throws protocolerror and doesnt work.

I can post using postman.

I can get data using pretty much the exact same function except for a few changes.

Post just isnt working for me.

public static async Task<string> PostData(string url, string data)
{
      using(UnityWebRequest request = UnityWebRequest.Post(url, data))
        {
            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("Accept", "application/json");
            var operation = request.SendWebRequest();
            while(!operation.isDone)
            {
                await Task.Yield();
                Debug.Log($"({request.downloadProgress}%)");
            }
            if(request.isHttpError || request.isNetworkError)
            {
                Debug.Log("Request failed...");
                return null;
            }
            if(request.result == UnityWebRequest.Result.Success)
                return request.downloadHandler.text;
            return null;
        }
}

2 Answers

2

Well, this is a common pitfall with Unity’s Post method. For some reason they throught it’s a great idea that by default any Post request will send url encoded data which is extremely unintuitive. See the exact implementation here.

If you want to post raw text / json / binary / whatever you have to provide your own UploadHandlerRaw and provide your data that way.

I quickly setup a php script like this:

<?php
    $postData = file_get_contents("php://input");
    $request = json_decode($postData, true);
    $request["result"] = "FooBar";
    $result = json_encode($request, JSON_PRETTY_PRINT);
    header("Content-Type", "application/json");
    echo $result;
?>

and added this line before your SendRequest line:

request.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(data));

This will replace the upload handler with our own and we simply perform an UTF8 encoding on the text.

I used my SimpleJSON (since I already had it in my project) just to run this example:

async void Start()
{
    JSONNode n = new JSONObject();
    n["test"] = 42;
    Debug.Log("Request: " + n.ToString(3));
    string res = await PostData("MyURL/php/JsonTest.php", n.ToString());
    var node = JSON.Parse(res);
    Debug.Log("Response: " + node.ToString(3));
}

So the php script will parse the json into an object, add a new field called “result” and simply return whatever was send in to the client. The two log statements in Unity look like this:

Request: {
   "test" : 42
}

Response: {
    "test" : 42,
    "result" : "FooBar"
}

So this works as expected once you use a raw upload handler.

Hmm, i tried what you suggested and im getting this as an error now HTTP/1.1 400 Bad Request Do you know if my web service only allowing https would cause an error?

hmm, my body was coming in as something like Text.File.Json or something similar. So my asp.net app was looking for a string

PostFunction([FromBody]string data)

But Unity, or my code dunno, was sending it as the Text.File.Json or whichever it was. So I changed my code to

PostFunction([FromBody]object data)

Which, when debugging it locally, caused it to actually hit my breakpoint and start the function.

Hope this helps anybody else trying to Post to an asp.net web api.
Goodluck