Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will this work in dot net 6 in a docker container? #8

Open
RobotX5 opened this issue Mar 17, 2022 · 6 comments
Open

Will this work in dot net 6 in a docker container? #8

RobotX5 opened this issue Mar 17, 2022 · 6 comments

Comments

@RobotX5
Copy link

RobotX5 commented Mar 17, 2022

Will this work in dot net 6 in a docker container?
Do you have any patterns/examples now that startup.cs is removed?

based on my testing it seems to be failing on string text = new StreamReader(Request.Body).ReadToEnd(); call.
I don't currently have access to the docker logs in prd so I am not exactly sure what is failing.

Thanks

@CarloP95
Copy link

CarloP95 commented Apr 22, 2022

I'm trying to create an Alexa skill for my studies and i can say that it seems not to work seamlessly.

I have the same setup you are talking about: .Net 6 and the skill will be deployed in a docker container.

The problem is in this piece of code:

private static async Task<string> GetBodyFromRequestAsync(HttpRequest httpRequest)
{
            httpRequest.Body.Position = 0;
            var body = await httpRequest.ReadAsStringAsync();
            httpRequest.Body.Position = 0;

            return body;
}

Since it sets the position of the body it gives System.NotSupportedException with the following error
An unhandled exception has occurred while executing the request. System.NotSupportedException: Specified method is not supported. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.set_Position(Int64 value) at Alexa.NET.Security.Functions.AlexaRequestValidationFunctionsExtension.GetBodyFromRequestAsync(HttpRequest httpRequest).

Then, if you try to fix with Request.EnableBuffering() as someone suggests on various issues of Asp.NET core, the ReadAsStringAsync starts to complain about not finding a type into an assembly as follows.

System.TypeLoadException: Could not load type 'Microsoft.AspNetCore.Http.Internal.BufferingHelper' from assembly 'Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. at Microsoft.Azure.WebJobs.Extensions.Http.HttpRequestExtensions.ReadAsStringAsync(HttpRequest request)

I'm working on a solution, but any suggestion will be appreciated,
Regards

@CarloP95
Copy link

I found the solution.

If you want to use the SkillRequest.ValidateRequestAsync extension method it is necessary to configure your .Net 6 Program.cs with the following middleware. It must be done before any app.Use but not before Swagger middleware if you're using it

app.Use((context, _next) =>
{
    context.Request.EnableBuffering();
    return _next(context);
});

If you want to use the middleware with the app.UseAlexaRequestValidation you must change the Invoke method in the following way

            // CHANGES: no more context.Request.EnableRewind()
            context.Request.EnableBuffering();
            
            // Verify SignatureCertChainUrl is present
            context.Request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
            if (String.IsNullOrWhiteSpace(signatureChainUrl))
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return;
            }

            Uri certUrl;
            try
            {
                certUrl = new Uri(signatureChainUrl);
            }
            catch
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return;
            }

            // Verify SignatureCertChainUrl is Signature
            context.Request.Headers.TryGetValue("Signature", out var signature);
            if (String.IsNullOrWhiteSpace(signature))
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return;
            }
            // CHANGES: read the body async
            string body = await new StreamReader(context.Request.Body).ReadToEndAsync();
            context.Request.Body.Position = 0;

            if (String.IsNullOrWhiteSpace(body))
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return;
            }
            var valid = await RequestVerification.Verify(signature, certUrl, body);
            if (!valid)
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return;
            }

            await _next(context);

Just a final tip:

If your using this netstandard2.0 project in your .Net 6 application, you can encounter some problems with Assembly info. I fixed them by adding the following lines to your .csproj

    <PropertyGroup>
        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    </PropertyGroup>

If you want, i made a fork for using this library in an application.
Regards

@RobotX5
Copy link
Author

RobotX5 commented Apr 25, 2022

this looks like it will help although i am having an issue adding the project to my solution. did you upgrade the solution to dot net 6 if so can you please check that in to your branch. I can not get your branch to work.

@CarloP95
Copy link

You're right.. I've integrated the library with git submodules.

There should be no problems using a netstandard library with .NET 6 except the one i described above.
I'll do a sample and upload it as soon as i can

@CarloP95
Copy link

CarloP95 commented May 8, 2022

I've just seen what i've done.

Since i've done a git clone into the directory of my Alexa Skill, Visual Studio saw that code as if it was part of my project and not a netstandard 2.0 library.

As a workaround you can do the same thing. In my spare time i'll investigate if it works as a standalone library

@CarloP95
Copy link

CarloP95 commented May 8, 2022

I've done some experiments upgrading the library in netstandard2.1 to use C#8.0 (you can find everything in the netstandard2.1 branch); i've fixed dependency problems and then i attached the two libraries (middleware and functions) as projects to my Alexa Skill Solution.

Then i started debugging everything but i keep getting this error.

System.MissingMethodException: Method not found: 'System.Threading.Tasks.Task`1<Boolean> Alexa.NET.Request.RequestVerification.Verify(System.String, System.Uri, System.String)'.
   at Alexa.NET.Security.Middleware.AlexaRequestValidationMiddleware.Invoke(HttpContext context)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Alexa.NET.Security.Middleware.AlexaRequestValidationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Since i've already got Alexa.Net in the dependencies of all project i assume that is a runtime problem of netstandard2.1 and .net6.0; maybe some runtime error since in the MS documentation is written that

The only reason to retarget from .NET Standard to .NET 5+ would be to gain access to more runtime features, language features, or APIs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants