8

I am creating a Registration Scene on Unity. On the backend I have NodeJS server with MongoDB. Registration is successful and data is saved on Mongo too.

This is my NodeJS api for register

api.post('/register', (req,res) => {
Account.register(new Account({username: req.body.username}), req.body.password, function(err, account){
  console.log("acc: "+account);
  if(err){
    if (err.name == "UserExistsError") {
      console.log("User Exists");
      return res.status(409).send(err);
    }else {
      console.log("User Error 500");
      return res.status(500).send(err);
    }
  }else {
    let newUser = new User();
    newUser.accountid = account._id;
    newUser.name = req.body.fullname;
    newUser.gender = req.body.gender;
    newUser.role = req.body.role;
    newUser.country = req.body.country;
    newUser.coins = req.body.coins;
    newUser.save(err => {
      if(err){
        console.log(err);
        return res.send(err);
      }else{
        console.log('user saved');
        res.json({ message: 'User saved' });
      }
    });
    passport.authenticate(
      'local', {
        session: false
      })(req,res, () => {
         res.json({ registermsg: 'Successfully created new account'});
      });
  }
});
});

And this is my POST co-routine in Unity C#

IEnumerator Post(string b) {

    byte[] bytes = System.Text.Encoding.ASCII.GetBytes(b);

    using (UnityWebRequest www = new UnityWebRequest(BASE_URL, UnityWebRequest.kHttpVerbPOST)) {
        UploadHandlerRaw uH = new UploadHandlerRaw(bytes);
        www.uploadHandler = uH;
        www.SetRequestHeader("Content-Type", "application/json");
        yield return www.Send();

        if (www.isError) {
            Debug.Log(www.error);
        } else {
            lbltext.text = "User Registered";
            Debug.Log(www.ToString());
            Debug.Log(www.downloadHandler.text);
        }
    }
}

I am trying to Debug.Log(www.downloadHandler.text); but I get NullReferenceException.

I'd like to ask, is the way I am using to return response in my api correct? If yes, how can I use that response in Unity side.

Luzan Baral
  • 3,678
  • 5
  • 37
  • 68

2 Answers2

14

UnityWebRequest.Post, UnityWebRequest.Get and other UnityWebRequest functions that creates new instance of UnityWebRequest, will automatically have DownloadHandlerBuffer attached to it.

Now, if you create new instance of UnityWebRequest with the UnityWebRequest constructor, DownloadHandler is not attached to that new instance. You have to manually do that with DownloadHandlerBuffer.

IEnumerator Post(string b)
{

    byte[] bytes = System.Text.Encoding.ASCII.GetBytes(b);

    using (UnityWebRequest www = new UnityWebRequest(BASE_URL, UnityWebRequest.kHttpVerbPOST))
    {
        UploadHandlerRaw uH = new UploadHandlerRaw(bytes);
        DownloadHandlerBuffer dH = new DownloadHandlerBuffer();

        www.uploadHandler = uH;
        www.downloadHandler = dH;
        www.SetRequestHeader("Content-Type", "application/json");
        yield return www.Send();

        if (www.isError)
        {
            Debug.Log(www.error);
        }
        else
        {
            lbltext.text = "User Registered";
            Debug.Log(www.ToString());
            Debug.Log(www.downloadHandler.text);
        }
    }
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks, I was confused on using `DownloadHandlerBuffer`. But now I get `Can't send headers after they are set.` I read lot's of question but could not make my code work as per them. – Luzan Baral Apr 08 '17 at 11:53
  • I was planning to rename the title to "UnityWebRequest.downloadHandler returning null". That will help many people that will run into this problem. It would be nice to create a new question for your new header problem. Better if you describe what that problem is. – Programmer Apr 08 '17 at 11:55
  • Okay, I'll change the question. – Luzan Baral Apr 08 '17 at 11:55
  • Maybe [this](http://stackoverflow.com/questions/34983520/express-js-routing-error-cant-set-headers-after-they-are-sent)? Will be away for hours and can't reply until I return. – Programmer Apr 08 '17 at 12:08
  • Okay, I'm also going through other Q&As related to same problem. Thanks again. – Luzan Baral Apr 08 '17 at 12:12
  • I fixed the code by changing the nested structure of the code in my Node API, and updated code in my question. – Luzan Baral Apr 10 '17 at 05:13
  • Why don't they have it attach automatically? – Evorlor Apr 30 '18 at 20:40
  • I know this is probably a question for someone at Unity, but maybe you'll know. Why is it not attached when using a null constructor? Is there any benefit to leaving it as null? – Evorlor Apr 30 '18 at 20:43
  • 1
    @Evorlor I don't know what "null constructor" is and I only talked about constructor not "null constructor". When you create new instance of `UnityWebRequest` with its constructor like you would normally do, `DownloadHandlerBuffer` is not attached. If you create new instance of `UnityWebRequest` with the `UnityWebRequest.Post` or `UnityWebRequest.Get` functions, those functions will automatically attach `DownloadHandlerBuffer` to it because 90% of the time, people need to access the data from server in a Get/Post request. – Programmer Apr 30 '18 at 21:10
  • 1
    If you just want to make a request but don't care about the data sent by the data, why would you want `DownloadHandlerBuffer` to be attached to `UnityWebRequest`? If you want to [stream](https://stackoverflow.com/questions/49524324/obtain-data-from-unitywebrequest-while-still-downloading/49533859#49533859) or access the data while it's still being received, why would you want Unity to attach `DownloadHandlerBuffer`? It's totally useless here and `DownloadHandlerScript` is needed instead of `DownloadHandlerBuffer`. – Programmer Apr 30 '18 at 21:10
  • 1
    If you want to efficiently download a texture, why should Unity attach `DownloadHandlerBuffer` when `DownloadHandlerTexture` is needed and here and used to decompression texture on a worker Thread? It's not attached because creating new instance of UnityWebRequest means that you are doing something custom so you've got to write more code. Unity wants to give you control . I am sure there are many other reasons. – Programmer Apr 30 '18 at 21:10
  • By attaching `DownloadHandlerBuffer` when it's not needed, you are unnecessary allocating memory on the heap and making it run unnecessary processing on the native(C++) side. So memory space + cpu time = wasted. – Programmer Apr 30 '18 at 21:15
1

You simplly need to attach a DownloadHandlerBuffer , you don't need a new UnityWebRequest!

DownloadHandlerBuffer dH = new DownloadHandlerBuffer(); www.downloadHandler = dH;

ivan.rosina
  • 368
  • 3
  • 9