Reputation: 174
I am trying to POST a json string to a web API and currently got this code:
async Task<Uri> Post(CapturedImage image)
{
string json = JsonConvert.SerializeObject(image);
var content = new StringContent(json.ToString(), Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
Debug.Log("Request Message Information:- \n\n" + response.RequestMessage + "\n");
Debug.Log(json.ToString());
// return URI of the created resource.
return response.Headers.Location;
}
The code is not done yet so I'm not sure this is the type I want to return in the end (in the end I will have a new json string with information about a specific car supposedly).
Unity hangs when it comes to the line HttpResponseMessage response = await client.PostAsync(url, content);
and I have to forcefully close the unity app.
How can I use the httpClient
successfully? I am not using the unityWebRequest
for the moment because I don't understand in which way WWWForm
is being sent (like an object I guess). And I don't want a byte[] to be sent either, but a json string and I can assume that the WWWForm
is like a json string but separated-ish. Also I don't get which type to be received in the web API either when its a WWWForm
. Like if its a json string I just have the parameter like (string json)
.
Am I thinking completely wrong with not using unityWebRequest
instead of httpClient
? I have to use json if possible.
Upvotes: 0
Views: 5660
Reputation: 90871
UnityWebRequest.Post(string URL, string data)
also takes string
as data input not only a WWWForm
.
Usually you would use it in a Coroutine
In order to get a result back you could add a simple callback
IEnumerator Upload(string URL, string jsonData, Action<string> callback)
{
using (UnityWebRequest www = UnityWebRequest.Post(URL, jsonData))
{
www.SetRequestHeader("Content-Type", "application/json");
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
callback?.Invoke(www.GetResponseHeader("Location"));
}
}
}
and use it with
StartCoroutine(Upload(someURL, someJsonData,
// e.g. as lambda expression
result =>
{
Debug.Log(result);
}
));
or with a method
StartCoroutine(Upload(someURL, someJsonData, HandleUploadResult);
...
private void HandleUploadResult(string result)
{
Debug.Log(result);
}
But if you really need it to be used with await
as said this looks promising (though neevr tried it):
public class UnityWebRequestAwaiter : INotifyCompletion
{
private UnityWebRequestAsyncOperation asyncOp;
private Action continuation;
public UnityWebRequestAwaiter(UnityWebRequestAsyncOperation asyncOp)
{
this.asyncOp = asyncOp;
asyncOp.completed += OnRequestCompleted;
}
public bool IsCompleted { get { return asyncOp.isDone; } }
public void GetResult() { }
public void OnCompleted(Action continuation)
{
this.continuation = continuation;
}
private void OnRequestCompleted(AsyncOperation obj)
{
continuation();
}
}
public static class ExtensionMethods
{
public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOp)
{
return new UnityWebRequestAwaiter(asyncOp);
}
}
It looks complicated but ... you don't have to do anything with it just put it somewhere in your Assets
.
Then as far as I understand it you can simply use something like
www = UnityWebRequest.Post(URL, jsonData);
www.SetRequestHeader("Content-Type", "application/json");
await www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
var result = www.GetResponseHeader("Location");
}
There are other sources which do something similar .. maybe better?
Upvotes: 6