diff --git a/core/dotnet2.2/QUICKSTART.md b/core/dotnet2.2/QUICKSTART.md index 4498338..9494bd1 100644 --- a/core/dotnet2.2/QUICKSTART.md +++ b/core/dotnet2.2/QUICKSTART.md @@ -19,12 +19,20 @@ # Quick .NET Core 2.2 Action -A .NET Core action is a .NET Core class library with a method called `Main` that has the exact signature as follows: +A .NET Core action is a .NET Core class library with a method called `Main` or `MainAsync` that has the exact signature as follows: + +Synchronous: ```csharp public Newtonsoft.Json.Linq.JObject Main(Newtonsoft.Json.Linq.JObject); ``` +Asynchronous: + +```csharp +public async System.Threading.Tasks.Task MainAsync(Newtonsoft.Json.Linq.JObject); +``` + In order to compile, test and archive .NET Core projects, you must have the [.NET Core SDK](https://www.microsoft.com/net/download) installed locally and the environment variable `DOTNET_HOME` set to the location where the `dotnet` executable can be found. For example, create a C# project called `Apache.OpenWhisk.Example.Dotnet`: @@ -37,11 +45,13 @@ cd Apache.OpenWhisk.Example.Dotnet Install the [Newtonsoft.Json](https://www.newtonsoft.com/json) NuGet package as follows: ```bash -dotnet add package Newtonsoft.Json -v 12.0.2 +dotnet add package Newtonsoft.Json -v 13.0.1 ``` Now create a file called `Hello.cs` with the following content: +Synchronous example: + ```csharp using System; using Newtonsoft.Json.Linq; @@ -64,6 +74,32 @@ namespace Apache.OpenWhisk.Example.Dotnet } ``` +Asynchronous example: + +```csharp +using System; +using Newtonsoft.Json.Linq; +using System.Threading.Tasks; + +namespace Apache.OpenWhisk.Example.Dotnet +{ + public class Hello + { + public async Task MainAsync(JObject args) + { + await Task.Delay(10); // Just do a delay to have an async/await process occur. + string name = "stranger"; + if (args.ContainsKey("name")) { + name = args["name"].ToString(); + } + JObject message = new JObject(); + message.Add("greeting", new JValue($"Hello, {name}!")); + return (message); + } + } +} +``` + Publish the project as follows: ```bash @@ -79,17 +115,27 @@ zip -r -0 helloDotNet.zip * You need to specify the name of the function handler using `--main` argument. The value for `main` needs to be in the following format: -`{Assembly}::{Class Full Name}::{Method}`, e.q., -`Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main` +`{Assembly}::{Class Full Name}::{Method}`, e.q.: + ++ Synchronous: `Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main` ++ Asynchronous: `Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::MainAsync` ## Create the .NET Core Action To use on a deployment of OpenWhisk that contains the runtime as a kind: +Synchronous: + ```bash wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:2.2 ``` +Asynchronous: + +```bash +wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::MainAsync --kind dotnet:2.2 +``` + ## Invoke the .NET Core Action Action invocation is the same for .NET Core actions as it is for Swift and JavaScript actions: @@ -150,7 +196,7 @@ Install dependencies from the root directory on $OPENWHISK_HOME repository ```bash pushd $OPENWHISK_HOME ./gradlew install -podd $OPENWHISK_HOME +popd ``` Using gradle to run all tests diff --git a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj index ff84a8d..78fe3f5 100644 --- a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj +++ b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj @@ -28,7 +28,7 @@ 2.2.0 - 12.0.2 + 13.0.1 diff --git a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs index ab04deb..8cd47eb 100644 --- a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs +++ b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs @@ -17,6 +17,7 @@ using System; using System.IO; +using System.IO.Compression; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -88,23 +89,23 @@ public async Task HandleRequest(HttpContext httpContext) return (null); } - string base64Zip = message["code"].ToString(); string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString()); - string tempFile = Path.GetTempFileName(); - await File.WriteAllBytesAsync(tempFile, Convert.FromBase64String(base64Zip)); + string base64Zip = message["code"].ToString(); try { - System.IO.Compression.ZipFile.ExtractToDirectory(tempFile, tempPath); + using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64Zip))) + { + using (ZipArchive archive = new ZipArchive(stream)) + { + archive.ExtractToDirectory(tempPath); + } + } } catch (Exception) { await httpContext.Response.WriteError("Unable to decompress package."); return (null); } - finally - { - File.Delete(tempFile); - } Environment.CurrentDirectory = tempPath; diff --git a/core/dotnet3.1/QUICKSTART.md b/core/dotnet3.1/QUICKSTART.md index 2022a76..02cbfda 100644 --- a/core/dotnet3.1/QUICKSTART.md +++ b/core/dotnet3.1/QUICKSTART.md @@ -19,12 +19,20 @@ # Quick .NET Core 3.1 Action -A .NET Core action is a .NET Core class library with a method called `Main` that has the exact signature as follows: +A .NET Core action is a .NET Core class library with a method called `Main` or `MainAsync` that has the exact signature as follows: + +Synchronous: ```csharp public Newtonsoft.Json.Linq.JObject Main(Newtonsoft.Json.Linq.JObject); ``` +Asynchronous: + +```csharp +public async System.Threading.Tasks.Task MainAsync(Newtonsoft.Json.Linq.JObject); +``` + In order to compile, test and archive .NET Core projects, you must have the [.NET Core SDK](https://www.microsoft.com/net/download) installed locally and the environment variable `DOTNET_HOME` set to the location where the `dotnet` executable can be found. For example, create a C# project called `Apache.OpenWhisk.Example.Dotnet`: @@ -37,11 +45,13 @@ cd Apache.OpenWhisk.Example.Dotnet Install the [Newtonsoft.Json](https://www.newtonsoft.com/json) NuGet package as follows: ```bash -dotnet add package Newtonsoft.Json -v 12.0.2 +dotnet add package Newtonsoft.Json -v 13.0.1 ``` Now create a file called `Hello.cs` with the following content: +Synchronous example: + ```csharp using System; using Newtonsoft.Json.Linq; @@ -64,6 +74,32 @@ namespace Apache.OpenWhisk.Example.Dotnet } ``` +Asynchronous example: + +```csharp +using System; +using Newtonsoft.Json.Linq; +using System.Threading.Tasks; + +namespace Apache.OpenWhisk.Example.Dotnet +{ + public class Hello + { + public async Task MainAsync(JObject args) + { + await Task.Delay(10); // Just do a delay to have an async/await process occur. + string name = "stranger"; + if (args.ContainsKey("name")) { + name = args["name"].ToString(); + } + JObject message = new JObject(); + message.Add("greeting", new JValue($"Hello, {name}!")); + return (message); + } + } +} +``` + Publish the project as follows: ```bash @@ -79,17 +115,27 @@ zip -r -0 helloDotNet.zip * You need to specify the name of the function handler using `--main` argument. The value for `main` needs to be in the following format: -`{Assembly}::{Class Full Name}::{Method}`, e.q., -`Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main` +`{Assembly}::{Class Full Name}::{Method}`, e.q.: + ++ Synchronous: `Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main` ++ Asynchronous: `Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::MainAsync` ## Create the .NET Core Action To use on a deployment of OpenWhisk that contains the runtime as a kind: +Synchronous: + ```bash wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:3.1 ``` +Asynchronous: + +```bash +wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::MainAsync --kind dotnet:3.1 +``` + ## Invoke the .NET Core Action Action invocation is the same for .NET Core actions as it is for Swift and JavaScript actions: @@ -150,7 +196,7 @@ Install dependencies from the root directory on $OPENWHISK_HOME repository ```bash pushd $OPENWHISK_HOME ./gradlew install -podd $OPENWHISK_HOME +popd ``` Using gradle to run all tests diff --git a/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj b/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj index 588c031..719d367 100644 --- a/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj +++ b/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj @@ -26,7 +26,7 @@ - 12.0.3 + 13.0.1 diff --git a/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs b/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs index fd8732f..0a1a054 100644 --- a/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs +++ b/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs @@ -17,6 +17,7 @@ using System; using System.IO; +using System.IO.Compression; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -89,23 +90,23 @@ public async Task HandleRequest(HttpContext httpContext) return (null); } - string base64Zip = message["code"].ToString(); string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString()); - string tempFile = Path.GetTempFileName(); - await File.WriteAllBytesAsync(tempFile, Convert.FromBase64String(base64Zip)); + string base64Zip = message["code"].ToString(); try { - System.IO.Compression.ZipFile.ExtractToDirectory(tempFile, tempPath); + using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64Zip))) + { + using (ZipArchive archive = new ZipArchive(stream)) + { + archive.ExtractToDirectory(tempPath); + } + } } catch (Exception) { await httpContext.Response.WriteError("Unable to decompress package."); return (null); } - finally - { - File.Delete(tempFile); - } Environment.CurrentDirectory = tempPath; diff --git a/tests/src/test/scala/actionContainers/DotNet3_1ActionContainerTests_2_2.scala b/tests/src/test/scala/actionContainers/DotNet3_1ActionContainerTests_2_2.scala index c3002e7..6a8db7f 100644 --- a/tests/src/test/scala/actionContainers/DotNet3_1ActionContainerTests_2_2.scala +++ b/tests/src/test/scala/actionContainers/DotNet3_1ActionContainerTests_2_2.scala @@ -47,14 +47,14 @@ class DotNet3_1ActionContainerTests_2_2 extends BasicActionRunnerTests with WskA TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Environment::Main") } - override val testEnvParameters = { - TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Init::Main") - } - override val testEcho = { TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.AltEcho::Main") } + override val testEnvParameters = { + TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Init::Main") + } + val testEchoNoWrite = { TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::MainAsync") }