As you are seeing in the above image, I want to update User progress through this web service call.
For this I have to pass one block of array item and I can’t able to get success in this, individual item I have passed and its updating successfully within web server.
For passing array item, I became confused.
This kind of code, I have written:
[Serializable]
class GameProgress
{
public string sTargetLanguage;
public int nLevel;
public int nGame;
}
public void UpdateGameProgress()
{
// update score
StartCoroutine(UpdateGameProgressEnumerator());
IEnumerator UpdateGameProgressEnumerator()
{
WWWForm form = new WWWForm();
form.AddField(ARG_USER_ID, AdhocStorage.userProfile.userId.ToString());
GameProgress gameProgress = new GameProgress();
gameProgress.sTargetLanguage = AdhocStorage.userProfile.targetLanguage;
gameProgress.nLevel = GameManager.Instance.CurrentLevel.levelId;
gameProgress.nGame = GameManager.Instance.CurrentGame.gameId;
form.AddField(ARG_GAME_PROGRESS, JsonUtility.ToJson(gameProgress));
using (UnityWebRequest webRequest = UnityWebRequest.Post(GameConstants.HOOPSENGLISH_BASE_URL + GameConstants.WEB_UPDATE_USER_PROFILE_DATA_URI, form))
{
webRequest.SetRequestHeader(HEADER_AUTHORIZATION, AdhocStorage.userProfile.accessToken);
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
Debug.LogError("Error: " + webRequest.error);
break;
case UnityWebRequest.Result.ProtocolError:
Debug.LogError("HTTP Error: " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
Debug.Log("Received: " + webRequest.downloadHandler.text);
break;
}
}
}
On execution of this code, web server is giving me this kind of error message:
Error: I think, web developer has correct the mistake so now web service started working within the postman. But within Unity editor its started giving me. HTTP Error: HTTP/1.1 500 Internal Server Error
Make sure you’re sending the correct data.
You’re using JsonUtility.ToJson. The json utility Unity provides is very limited.
Rather than converting to json in the method call, put it into its own variable. var progressJson = JsonUtility.ToJson(gameProgress);
Then you can Debug.Log this and compare it to what you’re sending over postman, whether it is the same.
With the current given code, you’re probably getting
Which is an array named aProgress with 1 array element.
You can do this with JsonUtility as well but you’d have to create a wrapper class.
[Serializable]
public class GameProgress
{
public string sTargetLanguage;
public int nLevel;
public int nGame;
}
[Serializable]
public class GameProgressWrapper
{
public List<GameProgress> aProgress = new List<GameProgress>();
}
var progressWrapper = new GameProgressWrapper();
var gameProgress = new GameProgress();
gameProgress.sTargetLanguage = AdhocStorage.userProfile.targetLanguage;
gameProgress.nLevel = GameManager.Instance.CurrentLevel.levelId;
gameProgress.nGame = GameManager.Instance.CurrentGame.gameId;
progressWrapper.aProgress.Add(gameProgress);
var progressJson = JsonUtility.ToJson(progressWrapper);
Debug.Log(progressJson);
form.AddField(ARG_GAME_PROGRESS, progressJson);
That should give you the same json, but I’m not sure as I’ve not tested this. I wrote this straight from my mind.
I usually use Newtonsoft Json for this rather than Unity’s limited JsonUtility.
The issue is, in postman you’re posting a raw json input to the server. In Unity you use a form which is url-encoded and your json is just in a single field of that form data. You use the variable / constant ARG_GAME_PROGRESS as field name. If your server expects a raw json body, you must not use a form. We have countless of thread about the fact that the Post method is misleading when used with a “string body” as most people would assume it just uses the string data as raw data. But Unity decided that by default it uses url encoded text like it was form data. If you want to post raw json, you have to manually use an UploadHandlerRaw like shown in this thread for example .
Another common trick is to use Put instead, as it uses a raw upload handler by default, and then just change the method of the request to POST manually. It may be simpler, but I would highly recommend to add a comment to such hacks, so if other people have to look at your code it’s clear why you do such a strange thing. ^^
If you’re on a too old Unity version, you would need to use one of the workarounds I mentioned above. It looks like the new overload was introduced in version 2022.2. If your project is using an older version you have to use a workaround.
[Serializable]
public class GameProgress
{
public string sTargetLanguage;
public int nLevel;
public int nGame;
}
[Serializable]
public class GameProgressWrapper
{
public List<GameProgress> aProgress = new List<GameProgress>();
}
public void UpdateGameProgress()
{
// update score
StartCoroutine(UpdateGameProgressEnumerator());
IEnumerator UpdateGameProgressEnumerator()
{
var progressWrapper = new GameProgressWrapper();
var gameProgress = new GameProgress();
gameProgress.sTargetLanguage = AdhocStorage.userProfile.targetLanguage;
gameProgress.nLevel = GameManager.Instance.CurrentLevel.levelId;
gameProgress.nGame = GameManager.Instance.CurrentGame.gameId;
progressWrapper.aProgress.Add(gameProgress);
var progressJson = JsonUtility.ToJson(progressWrapper);
Debug.Log(progressJson);
using (UnityWebRequest webRequest = UnityWebRequest.Put(GameConstants.HOOPSENGLISH_BASE_URL + GameConstants.WEB_UPDATE_USER_PROFILE_DATA_URI, progressJson))
{
webRequest.method = UnityWebRequest.kHttpVerbPOST;
webRequest.SetRequestHeader(HEADER_AUTHORIZATION, AdhocStorage.userProfile.accessToken);
webRequest.SetRequestHeader("Content-Type", "application/json");
webRequest.SetRequestHeader("Accept", "application/json");
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
Debug.LogError("Error: " + webRequest.error);
break;
case UnityWebRequest.Result.ProtocolError:
Debug.LogError("HTTP Error: " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
Debug.Log("Received: " + webRequest.downloadHandler.text);
break;
}
}
}
}