Testing NativeAOT with Mock Lambda Test Tool results in error - c#

I have am using .NET 7 NativeAOT to write an AWS Lambda Function. I am trying to use the Mock Lambda Test Tool to test it. I'm not sure if I need to use the "Test Function" or "Executable Assembly"? How do I test it with the tool locally?
I'm using this input:
{
"Id": "test"
}
"Test Function" results in the following error:
System.ArgumentException: Object of type 'System.IO.MemoryStream' cannot be converted to type 'Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest'.
at System.RuntimeType.CheckValue(Object& value, ParameterCopyBackAction& copyBack, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Span`1 copyOfParameters, IntPtr* byrefParameters, Span`1 shouldCopyBack, ReadOnlySpan`1 parameters, RuntimeType[] sigTypes, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.ExecuteAsync(ExecutionRequest request) in C:\build\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 61
Executable Assembly does not appear to do anything.
I'm using VS Code in Linux. Here's my Lambda Function:
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Serialization.SystemTextJson;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DocGenerator;
public class Function
{
private static async Task Main()
{
Func<APIGatewayHttpApiV2ProxyRequest, ILambdaContext, Task<APIGatewayHttpApiV2ProxyResponse>> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>(options => {
options.PropertyNameCaseInsensitive = true;
}))
.Build()
.RunAsync();
}
public static async Task<APIGatewayHttpApiV2ProxyResponse> FunctionHandler(APIGatewayHttpApiV2ProxyRequest apigProxyEvent, ILambdaContext context)
{
System.Diagnostics.Debug.WriteLine("test");
context.Logger.LogLine("test");
var test = JsonSerializer.Deserialize(apigProxyEvent.Body, LambdaFunctionJsonSerializerContext.Default.Test);
return new APIGatewayHttpApiV2ProxyResponse
{
Body = test.Id.ToUpper(),
StatusCode = 200,
};
}
}
[JsonSerializable(typeof(APIGatewayHttpApiV2ProxyRequest))]
[JsonSerializable(typeof(APIGatewayHttpApiV2ProxyResponse))]
[JsonSerializable(typeof(Test))]
public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
{
}
public class Test {
public string Id {get; set;}
}
I used the samples here to create my function: https://github.com/aws-samples/serverless-dotnet-demo/tree/main/src/NET7Native

Related

Orleans 7.0 Serializer not working with POCOs originating from Nuget package

I have a Orleans 7.0 project with and I'm having an issue with the new default serializer.
The old serializer in Orleans 3.6.5 worked fine and it was serializing all the models and Dtos in the several internal Nuget packages.
Now in Orleans 7.0 the project does not recognize the models in the Nuget packages and I get this error:
Orleans.Serialization.CodecNotFoundException: Could not find a copier for type InternalProject.Model.
   at Orleans.Serialization.Serializers.CodecProvider.ThrowCopierNotFound(Type type) in /_/src/Orleans.Serialization/Serializers/CodecProvider.cs:line 666
   at Orleans.Serialization.Serializers.CodecProvider.GetDeepCopier[T]() in /_/src/Orleans.Serialization/Serializers/CodecProvider.cs:line 300
   at Orleans.Serialization.ServiceCollectionExtensions.CopierHolder`1.get_Value() in /_/src/Orleans.Serialization/Hosting/ServiceCollectionExtensions.cs:line 203
   at Orleans.Serialization.GeneratedCodeHelpers.OrleansGeneratedCodeHelper.GetService[TService](Object caller, ICodecProvider codecProvider) in /_/src/Orleans.Serialization/GeneratedCodeHelpers/OrleansGeneratedCodeHelper.cs:lin
e 75
   at OrleansCodeGen.InternalProject.Model.Copier_SpecificModel..ctor(ICodecProvider codecProvider) in C:\Projects\InternalProject.Model\Orleans.CodeGenerator\Orleans.CodeGenerator.Orle
ansSerializationSourceGenerator\InternalProject.Model.orleans.g.cs:line 20736
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance[T](IServiceProvider provider)
   at Orleans.Serialization.GeneratedCodeHelpers.OrleansGeneratedCodeHelper.GetService[TService](Object caller, ICodecProvider codecProvider) in /_/src/Orleans.Serialization/GeneratedCodeHelpers/OrleansGeneratedCodeHelper.cs:lin
e 72
Now for the interesting part: when I copy paste the exact same class in my main project I no longer get this error, and the class serializes perfectly fine.
I tried referencing the Nuget project directly in the main project(ProjectReference), the result is the same.
I only get rid of errors in two scenarios:
when I use the Json Serializer with IgnoreCycles (undesirable in my scenario, doesn't get rid of the underlying problem)
siloBuilder.Services.AddSerializer(sb =>
{
sb.AddJsonSerializer(
isSupported: type => type.Namespace.StartsWith("Nuget.Namespace"),
new JsonSerializerOptions()
{
ReferenceHandler = ReferenceHandler.IgnoreCycles
}
);
});
when I add the classes directly in the main project. Example class from the error:
[GenerateSerializer]
public sealed class Class1: Class1Base
{
public Class1()
{
}
public Class1(IRequest request, bool boolean, InternalClass internalClass)
: base(request, boolean)
{
InternalClass = internalClass;
}
[Id(0)]
public InternalClass InternalClass{ get; set; }
}
[GenerateSerializer]
public class Class1Base
{
public Class1Base()
{
}
public Class1Base(IRequest request, bool boolean)
{
Request = request;
Boolean= boolean;
}
[Id(0)]
public IRequest Request { get; set; }
[Id(1)]
public bool Boolean{ get; set; }
}

Can class-object bot state be saved in code while using Adaptive Dialogs in Bot Framework?

We are experiencing an issue with the Bot Framework where when one of the first steps is a CodeAction which performs an accessor.GetAsync() or .SetAsync(), the subsequent dialog accessing the property will crash with error:
[OnTurnError] unhandled error : Object of type 'Newtonsoft.Json.Linq.JValue' cannot be converted to type 'System.String'.
The full stack is here:
System.ArgumentException: Object of type 'Newtonsoft.Json.Linq.JValue' cannot be converted to type 'System.String'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at System.Reflection.PropertyInfo.SetValue(Object obj, Object value)
at Microsoft.Bot.Builder.Dialogs.ObjectPath.SetObjectSegment(Object obj, Object segment, Object value, Boolean json)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid5[T0,T1,T2,T3,T4](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
at Microsoft.Bot.Builder.Dialogs.ObjectPath.SetPathValue(Object obj, String path, Object value, Boolean json)
at Microsoft.Bot.Builder.Dialogs.Memory.DialogStateManager.SetValue(String path, Object value)
at Microsoft.Bot.Builder.Dialogs.Adaptive.Input.InputDialog.ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.DialogContext.ContinueDialogAsync(CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.Adaptive.AdaptiveDialog.ContinueActionsAsync(DialogContext dc, Object options, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.Adaptive.AdaptiveDialog.ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.DialogContext.ContinueDialogAsync(CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.DialogManager.HandleBotOnTurnAsync(DialogContext dc, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.DialogManager.OnTurnAsync(ITurnContext context, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.Dialogs.DialogManager.OnTurnAsync(ITurnContext context, CancellationToken cancellationToken)
at MyBot.Bot.MyBotBot`1.OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken) in H:\Work\MyBot\backendadaptivebot\api\Bots\MyBotBot.cs:line 50
at Microsoft.Bot.Builder.RegisterClassMiddleware`1.OnTurnAsync(ITurnContext turnContext, NextDelegate nextTurn, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.RegisterClassMiddleware`1.OnTurnAsync(ITurnContext turnContext, NextDelegate nextTurn, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.RegisterClassMiddleware`1.OnTurnAsync(ITurnContext turnContext, NextDelegate nextTurn, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.BotFrameworkAdapter.TenantIdWorkaroundForTeamsMiddleware.OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.MiddlewareSet.ReceiveActivityWithStatusAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)
at Microsoft.Bot.Builder.BotAdapter.RunPipelineAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)
In the RootDialog class constructor we have:
participantAccessor = _userState.CreateProperty<Profile>("profile");
string[] paths = { ".", "Dialogs", $"RootDialog.lg" };
string fullPath = Path.Combine(paths);
// These steps are executed when this Adaptive Dialog begins
Triggers = new List<OnCondition>()
{
// Add a rule to welcome user
new OnConversationUpdateActivity()
{
Actions = WelcomeUserSteps()
},
// Respond to user on message activity
new OnUnknownIntent()
{
Actions = GetUserDetails()
},
};
And GetUserDetails():
private static List<Dialog> GetUserDetails()
{
return new List<Dialog>()
{
new CodeAction(PopulateProfile),
new TextInput()
{
Prompt = new ActivityTemplate("${RequestPhoneNumber()}"),
Property = "user.profile.MobileNumber",
}
After this TextInput receives input from the user, the crash occurs.
However, if the CodeAction is removed, the bot does not crash.
Inside this PopulateProfile method we simply access the property which we created in the constructor, a basic Profile class (containing only simple properties: strings and an integer)
private static async Task<DialogTurnResult> PopulateProfile(DialogContext dc, System.Object options)
{
Profile profile = await participantAccessor.GetAsync(dc.Context, () => new Profile());
profile.Complete = 0;
return await dc.EndDialogAsync(options);
}
Notably, this creates an entry in the DialogContext State of type 'Profile' object as expected. However if we remove this CodeAction and replace with the following within GetUserDetails():
new SetProperty() {
Property = "user.profile.Complete",
Value = 0,
},
new TextInput()
{
Prompt = new ActivityTemplate("${RequestPhoneNumber()}"),
Property = "user.profile.MobileNumber",
}
Then the type of the object in DialogContext.State appears to be a JSON object, and the bot functions as expected.
Does this mean that adaptive dialogs in Bot Framework do not support the writing of properties as a POCO type via code?
So it must be done via simple direct values (e.g. user.profile.completed) or via SetProperty actions?
(I cannot see this documented anywhere)
Edit: Here's the simple Profile class:
public class Profile
{
public string Id { get; set; }
public string AssociatedAsset { get; set; }
public string FullName { get; set; }
public string PreferredName { get; set; }
public string MobileNumber { get; set; }
public string Email { get; set; }
public int Complete { get; set; } = 0;
}
You're trying to combine two largely-incompatible ways of doing things. State property accessors were the original way of accessing state in Bot Builder v4, but adaptive dialogs are a totally new system and they have their own way of accessing state.
Here's what's going wrong. Even though TextInput tries to assign a string to this.value, DialogStateManager.SetValue immediately converts that string to a JToken. So even if that JToken got retrieved as a string it would still be converted back to a JToken when assigning to user.profile.MobileNumber. And if user.profile has been serialized with type information then it will be deserialized as that type, which means it will get converted to a Profile object before the JToken is assigned to its MobileNumber property. You could raise this as a bug in the Bot Builder .NET GitHub repo, but be aware that you're trying to do something that goes against the design of adaptive dialogs.
If you want to use adaptive dialogs, you should be consistent about it and do everything the adaptive dialog way. It's easy to go wrong with code actions so they should be used sparingly. If the thing you're doing with a code action can be done with a different adaptive dialog action then you should use the different one because it will be incorporating builtin adaptive dialog functionality. For example, if you want to set a property then you should use SetProperty like you've seen.
If you really want to set a property in a code action then rather than using state property accessors you should do it the adaptive dialog way. Adaptive dialogs use SetValue to set their properties, so you should too. This will ensure that the data is formatted in a way that adaptive dialogs can easily consume.
private static async Task<DialogTurnResult> PopulateProfile(DialogContext dc, object options)
{
//var profile = await UserState.CreateProperty<Profile>("profile").GetAsync(dc.Context, () => new Profile());
//profile.Complete = 0;
dc.State.SetValue("user.profile.Complete", 0);
return await dc.EndDialogAsync(options);
}

Dependency injection fails to register class during startup of asp.net core web application

I am getting the following exception when program.cs calls CreateHostBuilder.Build():
System.InvalidOperationException : Unable to resolve service for type
'web_application.Models.postStatus' while attempting to activate
'web_application.Services.Updates.PostingStatusUpdater'.
Full error below, but it is being thrown at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
I searched for ways to turn on verbose logging for that dependency injection dll or ways to debug the dependency injection framework and couldn't find answers to that. If anyone knows how to enable verbose logging at this stage of the program, please free to help too!
This is how the service is being registered in Startup.cs:
using System;
...
namespace web_application
{
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IUpdateService<postStatus>, PostingStatusUpdater>();
...
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
...
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
postStatus is an enum, and my first thought was maybe DI registration was failing because of something related to it.
The actual class being registered derives from a base class, which implements the generic interface.
Generic Interface:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using web_application.Models;
namespace web_application.Services.Updates{
public interface IUpdateService<T>{
bool runPreUpdateChecks(out IList<string> allFailedChecks);
void runPostCheckHooks();
bool tryPerformUpdate(T intialState, T FinalState, Action runUpdate, out IList<string> failureReasons);
Task<(bool success, IList<string> updateFailureReasons)> tryPerformUpdateAsync(T intialState, T FinalState, Task runUpdateAsync);
}
}
The base class:
using System;
using System.Threading.Tasks;
using web_application.Models;
using System.Collections.Generic;
namespace web_application.Services.Updates{
public abstract class BaseStatusUpdater<T> : IUpdateService<T>
{
public T initStatus {get; private set;}
public T finalStatus {get; private set;}
// TODO: Add update check attributes
public List<PreUpdateCheck<T>> preUpdateChecks = new List<PreUpdateCheck<T>>();
public IList<Action> postUpdateHooks = new List<Action>();
public BaseStatusUpdater(T initStatus, T finalStatus){
this.initStatus = initStatus;
this.finalStatus = finalStatus;
}
/// <summary>
/// Runs preupdate checks and returns every check that failed (no short circuit)
/// Returns a list of failed checks on failure.
/// </summary>
public bool runPreUpdateChecks(out IList<string> allFailedChecks){
allFailedChecks = new List<string>(preUpdateChecks.Count);
var allChecksPassed = true;
foreach(var check in preUpdateChecks){
if(!check.run()){
allFailedChecks.Add(check.failureReason);
allChecksPassed = false;
}
}
return allChecksPassed;
}
/// <summary>
/// Run only actions that are one-off, and don't cascade into other
/// actions that may require custom error handling.
/// </summary>
public void runPostCheckHooks(){
foreach(var hook in postUpdateHooks){
hook();
}
}
public bool tryPerformUpdate(T intialState, T FinalState, Action runUpdate, out IList<string> updateFailureReasons){
if(!runPreUpdateChecks(out updateFailureReasons)){
return false;
}
runUpdate();
runPostCheckHooks();
return true;
}
// https://stackoverflow.com/questions/18716928/how-to-write-an-async-method-with-out-parameter
public async Task<(bool success, IList<string> updateFailureReasons)>
tryPerformUpdateAsync(T intialState, T FinalState, Task runUpdateAsync)
{
IList<string> updateFailureReasons = new List<string>(preUpdateChecks.Count);
if(!runPreUpdateChecks(out updateFailureReasons)){
return (false,updateFailureReasons);
}
await runUpdateAsync;
runPostCheckHooks();
return (true,updateFailureReasons);
}
}
}
The class being registered for IUpdateService
using System;
using web_application.Models;
using System.Collections.Generic;
namespace web_application.Services.Updates{
// Make this a singleton on injection to get this so that we don't keep constructing the things
// in the constructor every time its called? Or store the static logic somewhere else
using vpStatus = postStatus;
public class PostingStatusUpdater : BaseStatusUpdater<postStatus>
{
public PostingStatusUpdater(vpStatus vpsInitial, vpStatus vpsFinal)
: base(vpsInitial,vpsFinal)
{
Func<(bool,string)> isMovePermitted = () => {
if(UpdateLogic.permittedStatusChanges
.Contains(new UpdateLogic.statusPair(base.initStatus, vpsFinal))){
return (true,string.Empty);
}
return (false, "Cannot mark post as \"" + vpsFinal.ToString() + " since it is currently marked as "
+ "\"" + vpsInitial.ToString() + "\"");
};
var check1 = new PreUpdateCheck<vpStatus>(isMovePermitted);
base.preUpdateChecks.Add(check1);
}
}
}
There is not compile time error or warning about this, and I've been digging around to make sure this hasn't been addressed before but I can't find a question that addresses this exactly, so I thought I'd post this for help.
Thanks.
Full error:
Exception thrown: 'System.AggregateException' in
Microsoft.Extensions.DependencyInjection.dll: 'Some services are not
able to be constructed' Inner exceptions found, see $exception in variables window for more details.
Innermost exception
System.InvalidOperationException : Unable to resolve service for type
'web_application.Models.postStatus' while attempting to activate
'web_application.Services.Updates.PostingStatusUpdater'.
at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type
serviceType, Type implementationType, CallSiteChain callSiteChain,
ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache
lifetime, Type serviceType, Type implementationType, CallSiteChain
callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor
descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor
serviceDescriptor, CallSiteChain callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor
descriptor)

Alexa Skill request deserialization fails - json to SkillRequest object C#

I would like to get some help here, I am using Alexa.NET nuget package to develop a custom alexa skill using c#, I get the following error.
My Request to the Function(AWS Lambda):
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.[unique-value-here]",
"application": {
"applicationId": "amzn1.ask.skill.[unique-value-here]"
},
"user": {
"userId": "amzn1.ask.account.[unique-value-here]"
},
"attributes": {}
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.[unique-value-here]"
},
"user": {
"userId": "amzn1.ask.account.[unique-value-here]"
},
"device": {
"supportedInterfaces": {
"AudioPlayer": {}
}
}
}
},
"request": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.[unique-value-here]",
"timestamp": "2016-10-27T18:21:44Z",
"locale": "en-US"
}
}
The Deserialization Error:
System.Exception: Error deserializing the input JSON to type SkillRequest
at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.BuildParameters(ExecutionRequest request, ILambdaContext context) in C:\codebuild\tmp\output\src142363207\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 214
at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.ExecuteAsync(ExecutionRequest request) in C:\codebuild\tmp\output\src142363207\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 52
---------------- Inner 1 Exception ------------
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.BuildParameters(ExecutionRequest request, ILambdaContext context) in C:\codebuild\tmp\output\src142363207\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 202
---------------- Inner 2 Exception ------------
Amazon.Lambda.Serialization.SystemTextJson.JsonSerializerException: Error converting the Lambda event JSON payload to type Alexa.NET.Request.SkillRequest: Deserialization of reference types without parameterless constructor is not supported. Type 'Alexa.NET.Request.Type.Request'
at Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer.Deserialize[T](Stream requestStream)
---------------- Inner 3 Exception ------------
System.NotSupportedException: Deserialization of reference types without parameterless constructor is not supported. Type 'Alexa.NET.Request.Type.Request'
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(Type invalidType)
at System.Text.Json.JsonSerializer.HandleStartObject(JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader)
at System.Text.Json.JsonSerializer.ParseCore(ReadOnlySpan`1 utf8Json, Type returnType, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Deserialize[TValue](ReadOnlySpan`1 utf8Json, JsonSerializerOptions options)
at Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer.Deserialize[T](Stream requestStream)
SkillRequest.cs(From Alexa.NET nuget package):
public class SkillRequest
{
public SkillRequest();
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("session")]
public Session Session { get; set; }
[JsonProperty("context")]
public Context Context { get; set; }
[JsonProperty("request")]
public Type.Request Request { get; set; } //This is throwing the deserialization error
//See below for properties within this.
public System.Type GetRequestType();
}
Request property type in SkillRequest above(this is where the problem is I think):
[JsonConverter(typeof(RequestConverter))]
public abstract class Request
{
protected Request();
[JsonProperty("type", Required = Required.Always)]
public string Type { get; set; }
[JsonProperty("requestId")]
public string RequestId { get; set; }
[JsonProperty("locale")]
public string Locale { get; set; }
[JsonConverter(typeof(MixedDateTimeConverter))]
[JsonProperty("timestamp")]
public DateTime Timestamp { get; set; } // This might be the problem?
}
I tried different DateTime formats, I played around by removing properties, to see if it goes past the deserialization error, nothing seems to be working. Can someone help?
I had this same issue, serializing JSON as per an Alexa tutorial I was following. This post helped me to resolve it, however, I was not comfortable with the idea of rewriting the Alexa.net class locally, as it was used this way in working tutorials I was following.
According to: Amazon From .net core 3 there is a new JSON serializer used in the templates. It provides a performance benefit, but also seems to introduce this error with Alexa.Net.
[assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
was replaced by
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
The new serializer was throwing the 'parameterless constructor' error. After installing the Amazon.Lambda.Serialization.Json package via Nuget, and referencing the previous version of the serializer referenced in the tutorials I was following, all worked perfectly.
Just wanted to chime in with what worked for me.
I have a ASP.NET Core 3.1 Web API service I'm hitting from Alexa and was getting this same error. I added a reference to NuGet package Microsoft.AspNetCore.Mvc.NewtonsoftJson and then popped this into my Startup.cs file: services.AddControllers().AddNewtonsoftJson(); in the ConfigureServices() function.
Source: https://dotnetcoretutorials.com/2019/12/19/using-newtonsoft-json-in-net-core-3-projects/
Also looks like this was sort of reported as an issue
https://github.com/timheuer/alexa-skills-dotnet/issues/193

Switch from soap11 to soap12

I switched the protocol that I'm using in C# from
oCode.SoapVersion = SoapProtocolVersion.Soap11;
to
oCode.SoapVersion = SoapProtocolVersion.Soap12;
I get an error "WSE005: The input was not a valid SOAP message because it has either the wrong name or the wrong namespace. The name specified follows: Envelope. The namespace it was defined under follows: http://www.w3.org/2003/05/soap-envelope."
I can't find anything about what it means, there's nothing in Google with that message. Are there other things I need to consider when switching from 11 to 12? I didn't seem to find anyone else with the same issue.
Any help is welcome, thanks.
We're not using a WCF, but the
namespace System.Web.Services.Protocols
{
[ComVisible(true)]
public class SoapHttpClientProtocol : HttpWebClientProtocol
{
public SoapHttpClientProtocol();
[ComVisible(false)]
[DefaultValue(SoapProtocolVersion.Default)]
[WebServicesDescriptionAttribute("ClientProtocolSoapVersion")]
public SoapProtocolVersion SoapVersion { get; set; }
public void Discover();
protected IAsyncResult BeginInvoke(string methodName, object[] parameters, AsyncCallback callback, object asyncState);
protected object[] EndInvoke(IAsyncResult asyncResult);
protected virtual XmlReader GetReaderForMessage(SoapClientMessage message, int bufferSize);
protected override WebRequest GetWebRequest(Uri uri);
protected virtual XmlWriter GetWriterForMessage(SoapClientMessage message, int bufferSize);
protected object[] Invoke(string methodName, object[] parameters);
protected void InvokeAsync(string methodName, object[] parameters, SendOrPostCallback callback);
protected void InvokeAsync(string methodName, object[] parameters, SendOrPostCallback callback, object userState);
}
}
SOAP version 1.2 made a number of breaking changes, including the namespace of the SOAP envelope.
You didn't specify whether it was the client or the server code you changed, but one or other of the sides of this communication are not aware of the version change — probably the server, which is responding that it doesn't recognise the SOAP 1.2 envelope. If it doesn't support SOAP 1.2, you can't use this option.

Categories