Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,105 @@

[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
[![Build Status](https://travis-ci.com/apache/openwhisk-runtime-dotnet.svg?branch=master)](https://travis-ci.com/github/apache/openwhisk-runtime-dotnet)
## Give it a try today

Create a C# project called Apache.OpenWhisk.Example.Dotnet:

```bash
dotnet new classlib -n Apache.OpenWhisk.Example.Dotnet -lang "C#"
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.1
```

Now create a file called `Hello.cs` with the following content:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Example.Dotnet
{
public class Hello
{
public JObject Main(JObject args)
{
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
dotnet publish -c Release -o out
```

Zip the published files as follows:

```bash
cd out
zip -r -0 helloDotNet.zip *
```

Create the action

```bash
wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:2.2
```

For the return result, not only support `dictionary` but also support `array`

So a very simple `hello array` function would be:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloArray
{
public JArray Main(JObject args)
{
JArray jarray = new JArray();
jarray.Add("a");
jarray.Add("b");
return (jarray);
}
}
}
```

And support array result for sequence action as well, the first action's array result can be used as next action's input parameter.

So the function can be:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloPassArrayParam
{
public JArray Main(JArray args)
{
return (args);
}
}
}
```

## Changelogs

Expand Down
18 changes: 15 additions & 3 deletions core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public async Task HandleRequest(HttpContext httpContext)
JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body);

JObject valObject = null;
JArray valArray = null;

if (inputObject != null)
{
Expand All @@ -76,18 +77,29 @@ await Console.Error.WriteLineAsync(
}
}
}
if (valObject == null) {
valArray = inputObject["value"] as JArray;
}

object owObject = _constructor.Invoke(new object[] { });

try
{
JObject output;
JContainer output;

if(_awaitableMethod) {
output = (JObject) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valArray});
}
}
else {
output = (JObject) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) _method.Invoke(owObject, new object[] {valArray});
}
}

if (output == null)
Expand Down
18 changes: 15 additions & 3 deletions core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public async Task HandleRequest(HttpContext httpContext)
JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body);

JObject valObject = null;
JArray valArray = null;

if (inputObject != null)
{
Expand All @@ -75,19 +76,30 @@ await Console.Error.WriteLineAsync(
$"Unable to set environment variable for the \"{token.Path}\" token.");
}
}
if (valObject == null) {
valArray = inputObject["value"] as JArray;
}
}

object owObject = _constructor.Invoke(new object[] { });

try
{
JObject output;
JContainer output;

if(_awaitableMethod) {
output = (JObject) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valArray});
}
}
else {
output = (JObject) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) _method.Invoke(owObject, new object[] {valArray});
}
}

if (output == null)
Expand Down
33 changes: 33 additions & 0 deletions tests/dotnetshared/HelloArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloArray
{
public JArray Main(JObject args)
{
JArray jarray = new JArray();
jarray.Add("a");
jarray.Add("b");
return (jarray);
}
}
}
30 changes: 30 additions & 0 deletions tests/dotnetshared/HelloPassArrayParam.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloPassArrayParam
{
public JArray Main(JArray args)
{
return (args);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,32 @@ class DotNet2_2ActionContainerTests extends BasicActionRunnerTests with WskActor
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,32 @@ class DotNet3_1ActionContainerTests extends BasicActionRunnerTests with WskActor
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,32 @@ class DotNet3_1ActionContainerTests_2_2 extends BasicActionRunnerTests with WskA
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}