I get this error message in PlayStream when I call the function 'ForgotPassword':
"Payload": { "Source": "API", "FunctionName": "ForgotPassword", "ExecutionTimeMilliseconds": 0, "Result": { "ErrorCode": "CloudScriptAzureFunctionsHTTPRequestError", "Message": "Invocation of cloud script function ForgotPassword failed", "ErrorAndMessage": { "Item1": "CloudScriptAzureFunctionsHTTPRequestError", "Item2": "Invocation of cloud script function ForgotPassword failed" } }, "ResultTooLarge": false
And in Azure Portal:
2020-09-22T11:18:09.260 [Information] Executing 'ForgotPassword' (Reason='This function was programmatically called via the host APIs.', Id=fdf603b0-8d9f-462b-a38d-5a78d3e40cce) 2020-09-22T11:18:09.289 [Information] Run C# HTTP trigger function processed a request. 2020-09-22T11:18:09.330 [Information] The new password = ... 2020-09-22T11:18:09.331 [Information] The contact Email = ... 2020-09-22T11:18:09.331 [Information] TitleId = ... 2020-09-22T11:18:09.331 [Information] DeveloperSecretKey = ... 2020-09-22T11:18:09.593 [Error] Executed 'ForgotPassword' (Failed, Id=fdf603b0-8d9f-462b-a38d-5a78d3e40cce, Duration=334ms)Object reference not set to an instance of an object.
What is wrong with the function 'ForgotPassword'?
In addition, the Function URL is very long.
https://myplayfabfunctionapp.azurewebsites.net/api/ForgotPassword?code=JSXUqdml10yXBuZFYWVIcg%2FjMClz6PltkH7uYuPFpO2kmH0%2FjbU4tA%3D%3D
Is it normal that the Function URL is so long? I thought that the Function URL would always end with the function name, for example: https://myplayfabfunctionapp.azurewebsites.net/api/ForgotPassword
But in this case it doesn't end with the function name. I have registered the long Function URL and the Function name in my title account-->Functions-->Register Function.
Client code:
var result = await PlayFabCloudScriptAPI.ExecuteFunctionAsync(new ExecuteFunctionRequest() { Entity = new PlayFab.CloudScriptModels.EntityKey() { Id = entityid, Type = entitytype, }, FunctionName = "ForgotPassword", FunctionParameter = new { contactEmail = contactmail, newPassword = newpassword }, GeneratePlayStreamEvent = true });
Azure Function code:
namespace My.Functions { public static class NewFunction { [FunctionName("ChangeDisplayname")] public static async Task<dynamic> MakeApiCall( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req, ILogger log) { /* Create the function execution's context through the request */ var context = await FunctionContext<dynamic>.Create(req); var args = context.FunctionArgument; var desireddisplayname = args["NewDisplayname"]; /* Create the request object through the SDK models */ var request = new UpdateUserTitleDisplayNameRequest(); request.PlayFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId; request.DisplayName = desireddisplayname; /* Use the ApiSettings and AuthenticationContext provided to the function as context for making API calls. */ var adminApi = new PlayFabAdminInstanceAPI(context.ApiSettings, context.AuthenticationContext); /* The PlayFabServerAPI SDK methods provide means of making HTTP request to the PlayFab Main Server without any * extra code needed to issue the HTTP requests. */ return await adminApi.UpdateUserTitleDisplayNameAsync(request); } [FunctionName("ForgotPassword")] public static async Task<dynamic> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"{nameof(Run)} C# HTTP trigger function processed a request."); FunctionContext<dynamic> context = JsonConvert.DeserializeObject<FunctionContext<dynamic>>(await req.ReadAsStringAsync()); dynamic args = context.FunctionArgument; var contactEmail = args["contactEmail"]; var newPassword = args["newPassword"]; // retrieve the new password sent by the client, specified in ExecuteFunction -> FunctionParameter -> newPassword log.LogInformation($"The new password = {newPassword}"); log.LogInformation($"The contact Email = {contactEmail}"); //set up title id and secret key for admin api to use var adminApiSettings = new PlayFab.PlayFabApiSettings() { TitleId = "...", DeveloperSecretKey = "...", }; log.LogInformation($"TitleId = {adminApiSettings.TitleId}"); log.LogInformation($"DeveloperSecretKey = {adminApiSettings.DeveloperSecretKey}"); var adminAPI = new PlayFab.PlayFabAdminInstanceAPI(adminApiSettings); //get the Playfab ID from the contact email var userAccountInfoRequest = new LookupUserAccountInfoRequest { Email = contactEmail, }; var userAccountInfoDataResponse = await adminAPI.GetUserAccountInfoAsync(userAccountInfoRequest); string playfabID = userAccountInfoDataResponse.Result.UserInfo.PlayFabId; log.LogInformation($"PlayFabId = {playfabID}"); //log.LogInformation($"PlayFabId = {context.CallerEntityProfile.Entity.Id}"); //log.LogInformation($"PlayFabId = {context.CallerEntityProfile.Lineage.MasterPlayerAccountId}"); //get player's token stored in internal data var getUserInternalDataResponse = await adminAPI.GetUserInternalDataAsync(new PlayFab.AdminModels.GetUserDataRequest(){ PlayFabId = playfabID, //PlayFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId, Keys = new List<string> () {"Token"} }); var tokenId = getUserInternalDataResponse.Result.Data["Token"].Value; log.LogInformation($"tokenId = {tokenId}"); //reset the password return await adminAPI.ResetPasswordAsync(new PlayFab.AdminModels.ResetPasswordRequest() { Password = newPassword, Token = tokenId }); } } }