简体   繁体   中英

POST json string to webAPI from unity C#; HttpClient or UnityWebRequest?

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.

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM