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.
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
Which .Net Dependency Injection Frameworks Are Worth Looking Into
Jquery Ui Dialog With ASP.NET Button Postback
How to Execute an .SQL Script File Using C#
Question About Terminating a Thread Cleanly in .Net
Execute a Large SQL Script (With Go Commands)
Check Whether an Array Is a Subset of Another
Delete a File Being Used by Another Process
Update All Objects in a Collection Using Linq
Reading Settings from App.Config or Web.Config in .Net
Asp.Net Identity'S Default Password Hasher - How Does It Work and Is It Secure
Can My Enums Have Friendly Names
Why Does Adding a New Value to List≪≫ Overwrite Previous Values in the List≪≫
How to Get an Htmlelement Value Inside Frames/Iframes
Setting the Default Json Serializer in ASP.NET MVC