Closed devedse closed 5 years ago
Hi @devedse
Due to the way we deserialize Alexa requests, there isn't a scenario I'm aware of where using the base Request object would generate a valid representation of a skill request.
Can I ask which request type you're getting back from Alexa which is causing this issue for you? Or a snippet of the JSON you're receiving (anonymised of course) would be even more helpful.
Thank you
I tried to call the azure function with this JSON:
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.b76cb7b6-5c86-4238-a115-5c85e54abdbb",
"application": {
"applicationId": "amzn1.ask.skill.7539a510-6806-416a-a178-a28e16bdfe8f"
},
"user": {
"userId": "amzn1.ask.account.AG4PZGMCSU45ZMXLLNK2OGMNFIQRUQ7YAPM5NZTA4B7OPY56I2PLDX7AWNI5WALLFIMFADJBIB3WT66QMNRF7IVSTIOHTCUUMIIAQ26ZU3LOV3VO3X4IOXS6M2SK47JJX4ROP427WM7DKYVFIIMRDVNCMCCGKJE3JXXBEBZOPROPV3RRDXIY7B6LL3IXVWN657U2ZF64H5WA76Q"
}
},
"context": {
"System": {
"application": {
"applicationId": "amzn1.ask.skill.7539a510-6806-416a-a178-a28e16bdfe8f"
},
"user": {
"userId": "amzn1.ask.account.AG4PZGMCSU45ZMXLLNK2OGMNFIQRUQ7YAPM5NZTA4B7OPY56I2PLDX7AWNI5WALLFIMFADJBIB3WT66QMNRF7IVSTIOHTCUUMIIAQ26ZU3LOV3VO3X4IOXS6M2SK47JJX4ROP427WM7DKYVFIIMRDVNCMCCGKJE3JXXBEBZOPROPV3RRDXIY7B6LL3IXVWN657U2ZF64H5WA76Q"
},
"device": {
"deviceId": "amzn1.ask.device.AGPBVEN5YHL52MJERXS4CCTOWFTPRHS3JOYQVJ7SF7Z427GM5BZS22LIOHW7UYUYJLSDDYAJHYRUSDYYR4PJQNPIVONAZOFRJSCHXHJKFSIJKCS2XGWYD5G3ZAHT5ALMZOH2XXTLDK3QNIFRV4X2JODQY63Q",
"supportedInterfaces": {}
},
"apiEndpoint": "https://api.eu.amazonalexa.com",
"apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLjc1MzlhNTEwLTY4MDYtNDE2YS1hMTc4LWEyOGUxNmJkZmU4ZiIsImV4cCI6MTUzMDE5ODAzOCwiaWF0IjoxNTMwMTk0NDM4LCJuYmYiOjE1MzAxOTQ0MzgsInByaXZhdGVDbGFpbXMiOnsiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUdQQlZFTjVZSEw1Mk1KRVJYUzRDQ1RPV0ZUUFJIUzNKT1lRVko3U0Y3WjQyN0dNNUJaUzIyTElPSFc3VVlVWUpMU0REWUFKSFlSVVNEWVlSNFBKUU5QSVZPTkFaT0ZSSlNDSFhISktGU0lKS0NTMlhHV1lENUczWkFIVDVBTE1aT0gyWFhUTERLM1FOSUZSVjRYMkpPRFFZNjNRIiwidXNlcklkIjoiYW16bjEuYXNrLmFjY291bnQuQUc0UFpHTUNTVTQ1Wk1YTExOSzJPR01ORklRUlVRN1lBUE01TlpUQTRCN09QWTU2STJQTERYN0FXTkk1V0FMTEZJTUZBREpCSUIzV1Q2NlFNTlJGN0lWU1RJT0hUQ1VVTUlJQVEyNlpVM0xPVjNWTzNYNElPWFM2TTJTSzQ3SkpYNFJPUDQyN1dNN0RLWVZGSUlNUkRWTkNNQ0NHS0pFM0pYWEJFQlpPUFJPUFYzUlJEWElZN0I2TEwzSVhWV042NTdVMlpGNjRINVdBNzZRIn19.Wy0nX4mHd31Mw_tEHzZMO4voBuatWr-GJte5x-0BKnVgQL6esffS3W_CTe5EsaAIlpkFZLworBW710v-t7D9AhPkD7VYG6xFAXjrtdtREi49857JVXuHmk_hACqOFLOHQkqdv0l9Xklxdmhg9Yabd2PW9F3LxtFU4eZ-FqTZG8HUcbVnl5nycWalckUOAMHe6AFIt6X1_dWWWD8DHqMfQGi4n6aG3ZioiMq_DULEnhYRiezsk9nkESNnnBfNREbQhHdw5vvcRnoYPERRlWvkP4mBWvm2O03geS6Mt-j0ouuIA7OS52mBYiruHV8CDgGK5UvqkXBFfbDDA9kik9nevQ"
}
},
"request": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.eabb800a-5c31-4ea5-a637-24c1914a5956",
"timestamp": "2018-06-28T14:00:38Z",
"locale": "en-US",
"shouldLinkResultBeReturned": false
}
}
It seems however that indeed as you said there's something going wrong with the deserialization of the Request types.
Okay that's great - thank you. So the desired output should be that the property would have a LaunchRequest object in it.
First thing for me to check - are you using JSON.NET to Deserialize the JSON?
Sorry - that was a silly question, your original error message had Newtonsoft in it, I just didn't scroll enough.
Are you able to provide the JSON conversion code you're using in the function to get from the json to the SkillRequest object? Thanks.
Well with Azure Functions this all happens behind the scene I assume. So this is basically my code:
public static class Function1
{
[FunctionName("Alexa")]
public static async Task<SkillResponse> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] [FromBody]SkillRequest req, TraceWriter log)
{
SkillResponse response = null;
if (req?.Session?.User?.AccessToken != null)
{
ClaimsPrincipal principal = await Security.ValidateTokenAsync(req.Session.User.AccessToken);
if (principal != null)
{
PlainTextOutputSpeech outputSpeech = new PlainTextOutputSpeech();
string firstName = (req.Request as IntentRequest)?.Intent.Slots.FirstOrDefault(s => s.Key == "FirstName").Value?.Value;
outputSpeech.Text = "Hello " + firstName;
response = ResponseBuilder.Tell(outputSpeech);
}
}
return response;
}
}
}
I followed the tutorial from Microsoft here: https://blogs.msdn.microsoft.com/premier_developer/2018/01/25/amazon-alexa-skills-authenticated-by-azure-active-directory-and-backed-by-an-azure-function/
Basically just following all their steps results in the error I described.
Hi @devedse - sorry I haven't had chance to look at this until this morning.
I've put a working example here https://github.com/stoiveyp/Alexa.NET.Samples/tree/master/AzureFunction - worth mentioning it didn't work when the skill request object was actually named request, hence it called req
@stoiveyp, I'll check out the sample thanks. I indeed also ran into that error and submitted a Github post here: https://github.com/Azure/azure-functions-host/issues/3071 I'm quite stumped on how that error happens.
Hi, I am having the same issue from both my application and when using the sample code you provided @stoiveyp do we have any more information / work arounds? I was wondering if the json payload from amazon changed to simply be type request as opposed to a concrete type in Alexa.Net? Are there any plans to change request to a concrete type? (I noticed that this was implemented and then abandoned. ) Any information greatly appreciated.
EDIT1: Some supporting information...when passing in a payload like this { "version": "1.0", "session": { "new": true, "sessionId": "amzn1.echo-api.session.444c8b86-66eb-4a38-b2a6-48858c565e5d", "application": { "applicationId": "amzn1.ask.skill.4b5e4818-e543-48a3-a4eb-3045a08165e9" }, "user": { "userId": "amzn1.ask.account.QWERTY" } }, "context": { "System": { "application": { "applicationId": "amzn1.ask.skill.4b5e4818-e543-48a3-a4eb-3045a08165e9" }, "user": { "userId": "amzn1.ask.account.QWERTY" }, "device": { "deviceId": "amzn1.ask.device.AHX7C7S4HTLKPV3SXRIZA2N5IV4PNRWL2Y5TFG7DL3XLRIUFJIV4GZMCVDATZ6HUJGFRDLZFRF7KI7O5NMIFQPTATROUIC3ASZ4GMOAZDEERZIP3PRRB3XCZDW6LZFKXVX5ZVKY6BBTUWDK7X34DGQ7BT4MGDLEX7NIT6L4XRTMDA4BCZUCXC", "supportedInterfaces": {} }, "apiEndpoint": "https://api.amazonalexa.com", "apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLjRiNWU0ODE4LWU1NDMtNDhhMy1hNGViLTMwNDVhMDgxNjVlOSIsImV4cCI6MTUzNzE5NTk3MSwiaWF0IjoxNTM3MTkyMzcxLCJuYmYiOjE1MzcxOTIzNzEsInByaXZhdGVDbGFpbXMiOnsiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUhYN0M3UzRIVExLUFYzU1hSSVpBMk41SVY0UE5SV0wyWTVURkc3REwzWExSSVVGSklWNEdaTUNWREFUWjZIVUpHRlJETFpGUkY3S0k3TzVOTUlGUVBUQVRST1VJQzNBU1o0R01PQVpERUVSWklQM1BSUkIzWENaRFc2TFpGS1hWWDVaVktZNkJCVFVXREs3WDM0REdRN0JUNE1HRExFWDdOSVQ2TDRYUlRNREE0QkNaVUNYQyIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFHQk1NTjdZR0dSSEhTSFhGTUtFR1lDSE5LSk9WTFZYTU1SRzRBN0pTNU9aTUFWTUZNVUhTM0k2Mk1SMlJLR1U0UU5NWUo2TzVNVVFPNEhEV0s0UERRQ1YyQlpaVTdNNVNFVURCVUNHNzdTWkFSVUdPRTNVWlVINUlXWFlINVdMTEUyVzZTUDdXTkgzM0hQVVVSRTdNTjNQTEo3WFFJSlVTRFJCMlhJUUVCTFkzWVlGWFVONU5DSzVZRTVaUVQ0WU41NFNaVFZKVVZLRzRPUSJ9fQ.ZoqEZKOO2QWXN5R02ldaWf_oLFWTFg6mEu6pLaaQsyBrxtC7fVFTcmL30cMPfXvffEWyfORNTusZmDa9RVIb85QJ7b3l7ufRgO-luS3aPYv5KKt-V8ac0ns0LVkLnBbAescdfQeStl796Q1eMAq0ukVUWCgHIIkUHdFxnshfMZVN9WmbnAFn8PuLkrKdWMC8F7XRFRciZR4DkkCzdf3VwBpg-qN1HXMbJRZQ33J2qs6kTfk_bI3SGc_2LF3e6NTXoZz136r8H-doNFTU2oalVTtcPOgzJjuLiqvOX8orjPAMUKi4_JyxVS6ZwjOqYqtr81AIepgXSbaQwytSGCz7xg" } }, "request": { "type": "LaunchRequest", "requestId": "amzn1.echo-api.request.087b167f-722d-472f-b528-415e82441085", "timestamp": "2018-09-17T13:52:51Z", "locale": "en-US", "shouldLinkResultBeReturned": false } }
The Azure Function returns a 500 however if i manually change the request tag to be
"LaunchRequest": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.087b167f-722d-472f-b528-415e82441085",
"timestamp": "2018-09-17T13:52:51Z",
"locale": "en-US",
"shouldLinkResultBeReturned": false
}
The Azure Function returns a 200.
Hi @damienmccauley - the request type is the discriminating value that determines what fields should be available with each request, which is why request remains abstract.
I also got an error trying to re-run my old sample; so this still appears to be an issue with Azure Function bindings not honoring Json.Net custom converters. I've made a small update to the sample function to show that this is the case by manually deserializing the request inside the function - which should output json as expected.
[FunctionName("AlexaNetSample")]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]string req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
var request = JsonConvert.DeserializeObject<SkillRequest>(req);
if (request.Request is LaunchRequest)
{
return new OkObjectResult(ResponseBuilder.Tell("you launched from method param"));
}
return new OkObjectResult(ResponseBuilder.Empty());
}
Hope this is a suitable workaround
Thanks @stoiveyp, right you are on the AzureFuns bindings.
Hi All, There was a change in the HttpTrigger signature from version 1.0 to 2.0 of Azure Functions. The HttpRequest req parameter became HttpRequestMessage req
To work around this, I did the following
SkillRequest input = await req.Content.ReadAsAsync<SkillRequest>();
Here's a loose sample...
[FunctionName("AlexaSkill)]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
// Get to the content
SkillRequest input = await req.Content.ReadAsAsync<SkillRequest>();
string responseMessage = "";
switch (input.Request)
{
case LaunchRequest launch:
responseMessage = @"Welcome to the Machine";
break;
case IntentRequest intent:
switch (intent.Intent.Name)
{
case BuiltInIntent.Cancel:
case BuiltInIntent.Stop:
//blah blah
break;
default:
break;
}
break;
default:
break;
}
return new OkObjectResult(ResponseBuilder.Tell(responseMessage));
}
This one can be closed too? :)
One of the members of SkillRequest is named Request. Which is an abstract class. When using this code in Azure Functions, C# can't deserialize the JSON to an abstract class.
My proposal would be to remove the abstract part and make it a normal class.
Error:
Edit:
I created a pull request to fix this issue #100 .If you accept this, can you also make sure a new NuGet package will be published?Edit2: This pull request probably isn't the right way to solve it.