Sending Http Requests in C# With Unity

Sending http requests in C# with Unity

The WWW API should get this done but UnityWebRequest replaced it so I will answer the newer API. It's really simple. You have to use coroutine to do this with Unity's API otherwise you have have to use one of C# standard web request API and Thread. With coroutine you can yield the request until it is done. This will not block the main Thread or prevent other scripts from running.

Note:

For the examples below, if you are using anything below Unity 2017.2, replace SendWebRequest() with Send() and then replace isNetworkError with isError. This will then work for the lower version of Unity. Also, if you need to access the downloaded data in a binary form instead, replace uwr.downloadHandler.text with uwr.downloadHandler.data. Finally, the SetRequestHeader function is used to set the header of the request.

GET request:

void Start()
{
StartCoroutine(getRequest("http:///www.yoururl.com"));
}

IEnumerator getRequest(string uri)
{
UnityWebRequest uwr = UnityWebRequest.Get(uri);
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}

POST request with Form:

void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}

IEnumerator postRequest(string url)
{
WWWForm form = new WWWForm();
form.AddField("myField", "myData");
form.AddField("Game Name", "Mario Kart");

UnityWebRequest uwr = UnityWebRequest.Post(url, form);
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}

POST request with Json:

 void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com", "your json"));
}

IEnumerator postRequest(string url, string json)
{
var uwr = new UnityWebRequest(url, "POST");
byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
uwr.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
uwr.SetRequestHeader("Content-Type", "application/json");

//Send the request then wait here until it returns
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}

POST request with Multipart FormData/Multipart Form File:

void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}

IEnumerator postRequest(string url)
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("field1=foo&field2=bar"));
formData.Add(new MultipartFormFileSection("my file data", "myfile.txt"));

UnityWebRequest uwr = UnityWebRequest.Post(url, formData);
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}

PUT request:

void Start()
{
StartCoroutine(putRequest("http:///www.yoururl.com"));
}

IEnumerator putRequest(string url)
{
byte[] dataToPut = System.Text.Encoding.UTF8.GetBytes("Hello, This is a test");
UnityWebRequest uwr = UnityWebRequest.Put(url, dataToPut);
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}

DELETE request:

void Start()
{
StartCoroutine(deleteRequest("http:///www.yoururl.com"));
}

IEnumerator deleteRequest(string url)
{
UnityWebRequest uwr = UnityWebRequest.Delete(url);
yield return uwr.SendWebRequest();

if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Deleted");
}
}

[Unity]Is there a way that i can post http request when executing unity editor and after closing it?

Even though your question is quite broad ...


Yes there is!

You can use the UnityWebRequest in a way you usually wouldn't: Without a Coroutine. During opening the editor and closing it probably is not that bad if there is a short delay during the web request so we can use a simple blocking call in this specific use case.

So simply wait for it to finish in a usual while loop. I just created an example using a simple UnityWebRequest.Get to some random images on Google but you can easily replace it with any more complex UnityWebRequest.Post.

Simply start the Open request via InitializeOnLoadMethod and also register a callback to EditorApplication.wantsToQuit in order to call the close request when the Unity is tried to be closed. This way the Editor can only be closed if the callback for EditorApplication.wantsToQuit returned true.

Make sure to put this file into a folder called Editor.

using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

public static class Example
{
// InitializeOnLoadMethod causes this method to be called when the editor is opened
[InitializeOnLoadMethod]
private static void Initialize()
{
#region Required Part
// register callback
// The editor will only close if OnQuitEditor returns true
EditorApplication.wantsToQuit += OnQuitEditor;

// I'll just do a random Get Request but you can do any request here
var request = UnityWebRequest.Get("https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Example.svg/2000px-Example.svg.png");

request.SendWebRequest();

while (!request.isDone && !request.isHttpError && !request.isNetworkError)
{
// just wait
}

if(request.isHttpError || request.isNetworkError || !string.IsNullOrWhiteSpace(request.error))
{
Debug.LogError("Couldn't finish opening request!");
return;
}
#endregion Required Part

#region DEMO Part
// Just to show here that it worked create a file called "Open"
var filePath = Path.Combine(Application.streamingAssetsPath, "open.txt");
if (!Directory.Exists(Application.streamingAssetsPath)) Directory.CreateDirectory(Application.streamingAssetsPath);

using (var file = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
using (var writer = new StreamWriter(file))
{
writer.Write("Hello!");
}
}
#endregion DEMO Part
}

/// <summary>
/// Hinders the Editor to close if the request failed
/// </summary>
/// <returns></returns>
private static bool OnQuitEditor()
{
#region Required Part
// I'll just do a random Get Request but you can do any request here
var request = UnityWebRequest.Get("https://image.shutterstock.com/image-vector/example-red-square-grunge-stamp-260nw-327662909.jpg");

request.SendWebRequest();

while (!request.isDone && !request.isHttpError && !request.isNetworkError)
{
// just wait
}

if(request.isHttpError || request.isNetworkError || !string.IsNullOrWhiteSpace(request.error))
{
Debug.LogError("Couldn't finish closing request!");
return false;
}
#endregion Required Part

#region DEMO Part
// Just to show here that it worked delete the Open file and create a closed file
if (!Directory.Exists(Application.streamingAssetsPath)) Directory.CreateDirectory(Application.streamingAssetsPath);

var filePath = Path.Combine(Application.streamingAssetsPath, "open.txt");
if(File.Exists(filePath)) File.Delete(filePath);

filePath = Path.Combine(Application.streamingAssetsPath, "close.txt");

using (var file = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
using (var writer = new StreamWriter(file))
{
writer.Write("World!");
}
}
#endregion DEMO Part

return string.IsNullOrEmpty(request.error);
}
}

Note: Currently the editor could not be closed in the usual way in case the closing request fails so you might adjust this to your needs. If e.g. the result of the closing request is not that important you could rather add a simple void as callback to EditorApplication.quitting instead.


As a little demo that it works here you can see that when I open the project the Assets/StreamingAssets/open.txt is created.

When I close the project the Assets/StreamingAssets/open.txt is deleted and the Assets/StreamingAssets/closed.txt created instead.

Sample Image

Converting Http Request to Unity Web Request

After a lot of trial and error I figured it out. I hope this helps anyone else trying to do Unity Web Request:

 public void Send()
{
string uri = WBG_Config._EndPoint + "api/YOUR ROUTE HERE";
OAuth oAuth = new OAuth();

oAuth.Administrator = WBG_Config._OAuth_Admin;
oAuth.Password = WBG_Config._OAuth_Password;

string json = JsonConvert.SerializeObject(oAuth);

StartCoroutine(Post(uri, json));
}

IEnumerator Post(string url, string bodyJsonString)
{
var request = new UnityWebRequest(url, "POST");
byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");

yield return request.Send();

Debug.Log("Status Code: " + request.responseCode);

var response = request.downloadHandler.data;
string json = System.Text.Encoding.UTF8.GetString(response);
var _Response = JsonConvert.DeserializeObject<string>(json);

yield return _Response;

txtResponse.text = _Response;
}

}

How to write HTTP post request in Unity by using UnityWebRequest?


public void Request()
{
try
{
string url = "www.link.com";

var request = UnityWebRequest.Post(url, "");
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Accept", "text/csv");
request.SetRequestHeader("appKey", "ABC");
StartCoroutine(onResponse(request));
}
catch (Exception e) { Debug.Log("ERROR : " + e.Message); }
}
private IEnumerator onResponse(UnityWebRequest req)
{

yield return req.SendWebRequest();
if (req.isError)
Debug.Log("Network error has occured: " + req.GetResponseHeader(""));
else
Debug.Log("Success "+req.downloadHandler.text );
byte[] results = req.downloadHandler.data;
Debug.Log("Second Success");
// Some code after success

}

This code is worked for me...

The best way to make a GET request to a server in Unity

Note: The code in your question is performing a POST, not a GET. There's no such thing as 'get data'.

The following suggestion is equivalent from the server's point of view.

If you actually want a GET request - i.e. something totally different to what your code does - see the end of this answer.

Coroutines aren't threads

Wait until we have all of the data - This is where your framerate comes to die. This is because the Unity main thread - essentially your entire game - will wait for the server to respond with all of the data.

In short, that's just because of how coroutines work - they're very different from threads.

The general approach in Unity is to use WWW in a coroutine instead. Internally Unity runs the actual request on a separate thread and that coroutine just checks in on the progress every so often:

POST, matching your question's code:

// Build up the headers:
Dictionary<string,string> headers = new Dictionary<string,string>();

// Add in content type:
headers["Content-Type"] = "application/json";

// Get the post data:
byte[] postData = Encoding.GetEncoding("UTF-8").GetBytes(queryString);

// Start up the reqest:
WWW myRequest = new WWW(elk_url, postData, headers);

// Yield until it's done:
yield return myRequest;

// Get the response (into your JSON_String field like above)
// Don't forget to also check myRequest.error too.
JSON_String = myRequest.text;

// Load the JSON as an object and do magical things next.
// There's no need to add extra yields because
// your JSON parser probably doesn't support chunked json anyway.
// They can cover a few hundred kb of JSON in an unnoticeable amount of time.
....

GET, matching your question:

// Start up the reqest (Total guess based on your variable names):
// E.g. mysite.com/hello?id=2&test=hi
WWW myRequest = new WWW(elk_url + "?"+queryString);

// Yield until it's done:
yield return myRequest;

// Get the response
JSON_String = myRequest.text;
....


Related Topics



Leave a reply



Submit