question

andymaddison avatar image
andymaddison asked

CloudScriptAzureFunctionsHTTPRequestError when attempting to execute Azure function

I am using your guide to writing Playfab cloudscript with Azure.

As specified in your guide, I have first followed Microsoft's guide to creating my first Azure function. This works as expected and I can call via a browser.

I have added the function url in the Playfab dashboard, and have used the example code (modified) to execute it in my Unity project.

I get an error back:

CloudScriptAzureFunctionsHTTPRequestError

Invocation of cloud script function HttpExample failed

Code 400

I have checked everything. I'm using the entity id and type returned from the login call. The function name is correct, as is the parameter name.

Microsoft's function looks like this:

    public static class HttpExample
    {
        [FunctionName("HttpExample")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }
    }


This is how I'm calling it:

    IEnumerator ExecuteFunction()
    {
        print("entityId: " + entityId);
        print("entityType: " + entityType);

        var request = new ExecuteFunctionRequest()
        {
            Entity = new PlayFab.CloudScriptModels.EntityKey()
            {
                Id = entityId, //Get this from when you logged in,
                Type = entityType //Get this from when you logged in
            },
            FunctionName = "HttpExample", //This should be the name of your Azure Function that you created.
            FunctionParameter = new Dictionary<string, object>()
            {
                {"name","Mads"}
            },
            GeneratePlayStreamEvent = true
        };

        bool? success = null;
        ExecuteFunctionResult result = null;
        PlayFabError playFabError = null;

        PlayFabCloudScriptAPI.ExecuteFunction(request,(r) =>
        {
            result = r;
            success = true;
            print("ExecutionTimeMilliseconds: " + r.ExecutionTimeMilliseconds);
            print("FunctionName: " + r.FunctionName);
            print("FunctionResultTooLarge: " + r.FunctionResultTooLarge);
        }, (e) =>
        {
            playFabError = e;
            success = false;
            Error(e);
        });

        while (!success.HasValue) yield return null;

        print("success: " + success);
    }


CloudScript
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image Seth Du ♦ commented ·

Thanks for the feedback. We will follow the instruction you have posted to reproduce this issue. I will keep you informed if there are any updates.

0 Likes 0 ·

1 Answer

·
JayZuo avatar image
JayZuo answered

The problem here is that while calling ExecuteFunction, PlayFab will not pass the FunctionParameter to your Azure function as a normal HTTP request you've seen in Azure Function guide. Instead, PlayFab will set a context which includes the following information in the request body:

  • The Entity Profile of the caller
  • The Title Authentication Context
  • A boolean that indicates whether a Playsteam event is sent as part of the function being executed
  • The functions arguments used when calling the script

More details can be found at https://docs.microsoft.com/en-us/gaming/playfab/features/automation/cloudscript-af/cloudscript-af-context#use-the-context-model-when-executing-via-the-executefunction-api.

So in your Azure function, "data?.name;" won't get the FunctionParameter. And when you Register Function, I'd believe you you are setting the Function URL like

https://<functionappname>.azurewebsites.net/api/Httpexample

As there is also no "name" query string in the URL,

string name = req.Query["name"];

will also be null. So your Azure Function returns a "BadRequestObjectResult". And that's why you got the "CloudScriptAzureFunctionsHTTPRequestError" with ExecuteFunction method.

If you just want your Azure Function to be able to work, you can Register Function with the following Function URL:

https://<functionappname>.azurewebsites.net/api/HttpExample?name=Mads

If you need to change the name with FunctionParameter, you will need to change Azure function's code

name = name ?? data?.FunctionArgument?.name;

to get the name you've set in FunctionParameter with ExecuteFunction method.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Ward avatar image Ward commented ·

@Jay Zuo the final "FunctionArgument" comment gave me the answer I had been searching for for hours. Thanks! Where is this listed in the PlayFab documents? I seem to have missed it, and I've spent the last two days with Visual Studio Code, Postman, and my Azure subscription.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.