Reputation: 6850
I'm trying to do a post request on windows phone 8 from the Unity Platform. I do not want to use the unity WWW method as this blocks rendering (and is not thread safe).
The following code works in the editor and on Android, but when building it for WP8 I get the following error.
System.Byte[] System.Net.WebClient::UploadData(System.String,System.String,System.Byte[])` doesn't exist in target framework.
The reason for this error is explained here
It’s because Windows Phone 8 uses a different flavor of .NET called .NET for Windows Phone which is missing some of the types available on other platforms. You’ll have to either replace these types with different ones or implement them yourself. - http://docs.unity3d.com/Manual/wp8-faq.html
This is my code
using (WebClient client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/json";
byte[] requestData = new byte[0];
string jsonRequest = "{}";
if (data != null)
{
string tempRequest = Converter.SerializeToString (data);
jsonRequest = "{\"Data\": \"" + tempRequest + "\"}";
requestData = System.Text.Encoding.UTF8.GetBytes(jsonRequest);
}
// below line of code is the culprit
byte[] returnedData = client.UploadData(url, "POST", requestData);
if(returnedData.Length > 0)
{
// do stuff
}
}
I've also tried WebRequests, but GetResponse() breaks it, and HttpClient does not exist.
So, how do I post data in Unity, without using WWW, on windows phone 8?
UPDATE AS PER COMMENT REQUEST - WebRequests
This code, using HttpWebRequest works in the editor and on Android, but on windows phone throws the errors listed below the code.
var request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "POST";
var sw = new System.IO.StreamWriter(request.GetRequestStream(), System.Text.Encoding.UTF8);
sw.Write(jsonRequest); // jsonRequest is same variable as in above code, string with json object.
sw.Close();
var re = request.GetResponse();
string resultString = "";
using (var outputStream = new System.IO.StreamReader(re.GetResponseStream(), System.Text.Encoding.UTF8))
{
resultString = outputStream.ReadToEnd();
}
if(resultString.Length > 0)
{}
Error 1:
Error: method
System.IO.Stream System.Net.HttpWebRequest::GetRequestStream()
doesn't exist in target framework.
Error 2:
System.Net.WebResponse System.Net.HttpWebRequest::GetResponse()
doesn't exist in target framework.
UPDATE WITH MORE DETAILS - UploadStringAsync
Using this code to make an async request it again works great in the editor, errors are thrown on the WP8.
bool isCompleted = false;
byte[] returnedData = null;
client.UploadDataCompleted +=
new UploadDataCompletedEventHandler((object sender, UploadDataCompletedEventArgs e) =>
{
Debug.Log("return event");
returnedData = e.Result;
isCompleted =true;
});
Debug.Log("async call start");
client.UploadDataAsync(new Uri(url), requestData);
while(isCompleted == false){
Thread.Sleep(100);
}
if(returnedData.Length > 0)
{}
Error 1
method
System.Void System.Net.WebClient::add_UploadDataCompleted(System.Net.UploadDataCompletedEventHandler)
doesn't exist in target framework.
Error 2
Error: method
System.Void System.Net.WebClient::UploadDataAsync(System.Uri,System.Byte[])
doesn't exist in target framework.
Error 3
Error: type
System.Net.UploadDataCompletedEventArgs
doesn't exist in target framework.
Error 4
Error: method
System.Byte[] System.Net.UploadDataCompletedEventArgs::get_Result()
doesn't exist in target framework.
Upvotes: 9
Views: 824
Reputation: 6850
Go it to work on the windows phone using the code below. Compiles and runs in the editor, on Android and on WP8 (yay!). Haven't tried it on iOS yet.
Also wrote a post about it here: Create Web requests for unity that work on all platforms, even WP8
/// <summary>
/// Make post request to url with given paramaters
/// </summary>
/// <param name="url">URL to post data to http://server.com/method </param>
/// <param name="data">{ Data: data }</param>
/// <returns>string server response</returns>
public string PostData(string url, string data)
{
// json request, hard coded right now but use "data" paramater to set this value.
string jsonRequest = "{\"Data\": \"data\"}"; // the json request
var request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
// this could be different for your server
request.ContentType = "application/json";
// i want to do post and not get
request.Method = "POST";
// used to check if async call is complete
bool isRequestCallComplete = false;
// store the response in this
string responseString = string.Empty;
request.BeginGetRequestStream(ar =>
{
var requestStream = request.EndGetRequestStream(ar);
using (var sw = new System.IO.StreamWriter(requestStream))
{
// write the request data to the server
sw.Write(jsonRequest);
// force write of all content
sw.Flush();
}
request.BeginGetResponse(a =>
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new System.IO.StreamReader(responseStream))
{
// read in the servers response right here.
responseString = sr.ReadToEnd();
}
// set this to true so the while loop at the end stops looping.
isRequestCallComplete = true;
}, null);
}, null);
// wait for request to complete before continuing
// probably want to add some sort of time out to this
// so that the request is stopped after X seconds.
while (isRequestCallComplete == false) { Thread.Sleep(50); }
return responseString;
}
Upvotes: 1
Reputation: 976
I know you said you don't want to use the WWW class, but the reasons you gave to dont make sense IMO.
If you use a Coroutine to check the ".isDone" flag and not check it by using the Thread.Sleep() it wont block rendering and is thread safe (since unity only gives you access to its info on a single thread).
If you want to access the return data on another thread you just need to read that data in the main unity thread and then pass it along to whatever thread you want to use it on.
Unity by design is all runs on a single thread to make life easier for less experienced programmers. Though you should be able to create multiple threads using .NET threading, you will not be able to communicate directly with any Unity components, but you can pass the data back to Unity and wait until Update or another call by Unity to use the data. I know this doesnt answer your question exactly but if you cant solve it I think it would be worthwhile to look again at the WWW class and the best practices in using it.
Upvotes: 0
Reputation: 490
You cannot use these frameworks from unity because they are threaded / async / use another version of .Net
In short :
To do that on windows phone you will need to create a class library (two in fact) what unity calls a plugin
So why two dlls?
Because the editor needs a mockup dll (or the actual one if you want to implement it for desktop as well) that implements the same interface as the dll which is compatible on windows phone.
To be clear :
So you should implement that functionality in a dll, then reference that in unity, and finally call it directly.
All is explained here : http://docs.unity3d.com/Manual/wp8-plugins-guide-csharp.html
It is simpler than it looks like.
Upvotes: 0
Reputation: 12019
I don't know about any potential restrictions placed on you by Unity, but Windows Phone 8 has the WebClient.UploadStringAsync
method and the WebClient.UploadStringCompleted
event for doing just this.
HttpWebRequest
should also work (again, I don't know about any Unity limitations - see comment above asking for clarification).
Upvotes: 1