Skip to content

Commit

Permalink
Fixed property casing issue (Azure#154)
Browse files Browse the repository at this point in the history
* Fixed property casing issue

Signed-off-by: MD Ashique <[email protected]>

* Update src/Microsoft.Azure.WebJobs.Extensions.Dapr/DaprExtensionConfigProvider.cs

Co-authored-by: Shubham Sharma <[email protected]>

* Update src/Microsoft.Azure.WebJobs.Extensions.Dapr/Utils/DictionaryUtils.cs

Co-authored-by: Shubham Sharma <[email protected]>

* renaming variable

Signed-off-by: MD Ashique <[email protected]>

---------

Signed-off-by: MD Ashique <[email protected]>
Co-authored-by: Shubham Sharma <[email protected]>
  • Loading branch information
ASHIQUEMD and shubham1172 authored Sep 28, 2023
1 parent f8975dc commit 35d6f1a
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static class InvokeOutputBinding
[Function("InvokeOutputBinding")]
[DaprInvokeOutput(AppId = "{appId}", MethodName = "{methodName}", HttpVerb = "post")]
public static async Task<InvokeMethodParameters> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "invoke/{appId}/{methodName}")] HttpRequestData req, FunctionContext functionContext)
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "invoke/{appId}/{methodName}")] HttpRequestData req, FunctionContext functionContext)
{
var log = functionContext.GetLogger("InvokeOutputBinding");
log.LogInformation("C# HTTP trigger function processed a request.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ static DaprPubSubEvent CreatePubSubEvent(JToken arg)

static DaprPubSubEvent CreatePubSubEvent(JsonElement json)
{
if (!json.TryGetProperty("payload", out JsonElement payload))
var propertyBag = json.ToCaseInsensitiveDictionary();

if (!propertyBag.TryGetValue("payload", out JsonElement payload))
{
throw new ArgumentException($"A '{nameof(json).ToLowerInvariant()}' parameter is required for outbound pub/sub operations.");
}
Expand All @@ -160,12 +162,12 @@ static DaprPubSubEvent CreatePubSubEvent(JsonElement json)

DaprPubSubEvent event_ = new DaprPubSubEvent(payloadObject);

if (json.TryGetProperty("pubsubname", out JsonElement pubsubName))
if (propertyBag.TryGetValue("pubsubname", out JsonElement pubsubName))
{
event_.PubSubName = pubsubName.GetString();
}

if (json.TryGetProperty("topic", out JsonElement topic))
if (propertyBag.TryGetValue("topic", out JsonElement topic))
{
event_.Topic = topic.GetString();
}
Expand Down Expand Up @@ -227,7 +229,8 @@ private static DaprBindingMessage GetBindingMessageFromValueKindString(JsonEleme

private static DaprBindingMessage GetDaprBindingMessageFromValueKindObject(JsonElement jsonElement)
{
if (!jsonElement.TryGetProperty("data", out JsonElement data))
var propertyBag = jsonElement.ToCaseInsensitiveDictionary();
if (!propertyBag.TryGetValue("data", out JsonElement data))
{
throw new ArgumentException("A 'data' parameter is required for Dapr Binding operations.", nameof(jsonElement));
}
Expand All @@ -240,17 +243,17 @@ private static DaprBindingMessage GetDaprBindingMessageFromValueKindObject(JsonE

DaprBindingMessage message = new DaprBindingMessage(dataObj);

if (jsonElement.TryGetProperty("operation", out JsonElement operation))
if (propertyBag.TryGetValue("operation", out JsonElement operation))
{
message.Operation = JsonSerializer.Deserialize<string>(operation);
}

if (jsonElement.TryGetProperty("metadata", out JsonElement metadata))
if (propertyBag.TryGetValue("metadata", out JsonElement metadata))
{
message.Metadata = JsonSerializer.Deserialize<Dictionary<string, object>>(metadata);
}

if (jsonElement.TryGetProperty("bindingName", out JsonElement binding))
if (propertyBag.TryGetValue("bindingname", out JsonElement binding))
{
message.BindingName = JsonSerializer.Deserialize<string>(binding);
}
Expand All @@ -275,14 +278,15 @@ internal static DaprStateRecord CreateSaveStateParameters(JToken value)

internal static DaprStateRecord CreateSaveStateParameters(JsonElement parametersJson)
{
if (!parametersJson.TryGetProperty("value", out JsonElement value))
var propertyBag = parametersJson.ToCaseInsensitiveDictionary();
if (!propertyBag.TryGetValue("value", out JsonElement value))
{
throw new ArgumentException("A 'value' parameter is required for save-state operations.", nameof(parametersJson));
}

var parameters = new DaprStateRecord(value);

if (parametersJson.TryGetProperty("key", out JsonElement key))
if (propertyBag.TryGetValue("key", out JsonElement key))
{
parameters.Key = key.GetString();
}
Expand Down Expand Up @@ -314,22 +318,24 @@ internal static InvokeMethodParameters CreateInvokeMethodParameters(JsonElement
{
var options = new InvokeMethodParameters();

if (parametersJson.TryGetProperty("appId", out JsonElement appId))
var propertyBag = parametersJson.ToCaseInsensitiveDictionary();

if (propertyBag.TryGetValue("appid", out JsonElement appId))
{
options.AppId = appId.GetRawText();
}

if (parametersJson.TryGetProperty("methodName", out JsonElement methodName))
if (propertyBag.TryGetValue("methodname", out JsonElement methodName))
{
options.MethodName = methodName.GetRawText();
}

if (parametersJson.TryGetProperty("body", out JsonElement body))
if (propertyBag.TryGetValue("body", out JsonElement body))
{
options.Body = body;
}

if (parametersJson.TryGetProperty("httpVerb", out JsonElement httpVerb))
if (propertyBag.TryGetValue("httpverb", out JsonElement httpVerb))
{
options.HttpVerb = httpVerb.GetRawText();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------

namespace Microsoft.Azure.WebJobs.Extensions.Dapr.Utils
{
using System;
using System.Collections.Generic;
using System.Text.Json;

/// <summary>
/// Dictionary Utils.
/// </summary>
public static class DictionaryUtils
{
/// <summary>
/// Convert a JsonElement to a dictionary.
/// </summary>
/// <param name="element">JsonElement.</param>
/// <returns>Dictionary.</returns>
public static Dictionary<string, JsonElement> ToCaseInsensitiveDictionary(this JsonElement element)
{
var propertyBag = new Dictionary<string, JsonElement>(StringComparer.InvariantCultureIgnoreCase);

if (element.ValueKind == JsonValueKind.Null || element.ValueKind == JsonValueKind.Undefined)
{
return propertyBag;
}

foreach (var prop in element.EnumerateObject())
{
if (element.TryGetProperty(prop.Name, out JsonElement value) && value.ValueKind != JsonValueKind.Null)
{
propertyBag[prop.Name] = value;
}
}

return propertyBag;
}
}
}
104 changes: 104 additions & 0 deletions test/DaprExtensionTests/UnitTests/Utils/DictionaryUtilsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
namespace DaprExtensionTests.UnitTests.Utils
{
using System.Text.Json;
using Microsoft.Azure.WebJobs.Extensions.Dapr.Utils;
using Xunit;

public class DictionaryUtilsTests
{
[Fact]
public void ToCaseInsensitiveDictionary_PositiveCases()
{
// Arrange
var json = @"{
""Name"": ""John"",
""Age"": 30,
""City"": ""New York""
}";

var element = JsonDocument.Parse(json).RootElement;

// Act
var dictionary = element.ToCaseInsensitiveDictionary();

// Assert
Assert.Equal(3, dictionary.Count);
Assert.True(dictionary.ContainsKey("name"));
Assert.True(dictionary.ContainsKey("age"));
Assert.True(dictionary.ContainsKey("city"));
Assert.Equal("John", dictionary["name"].GetString());
Assert.Equal(30, dictionary["age"].GetInt32());
Assert.Equal("New York", dictionary["city"].GetString());
}

[Fact]
public void ToCaseInsensitiveDictionary_EmptyElement()
{
// Arrange
var json = @"{}";

var element = JsonDocument.Parse(json).RootElement;

// Act
var dictionary = element.ToCaseInsensitiveDictionary();

// Assert
Assert.Empty(dictionary);
}

[Fact]
public void ToCaseInsensitiveDictionary_NullValueProperties()
{
// Arrange
var json = @"{
""Name"": null,
""Age"": null
}";

var element = JsonDocument.Parse(json).RootElement;

// Act
var dictionary = element.ToCaseInsensitiveDictionary();

// Assert
Assert.Empty(dictionary);
}

[Fact]
public void ToCaseInsensitiveDictionary_NullElement()
{
// Arrange
JsonElement element = default;

// Act
var dictionary = element.ToCaseInsensitiveDictionary();

// Assert
Assert.Empty(dictionary);
}

[Fact]
public void ToCaseInsensitiveDictionary_DuplicateProperties()
{
// Arrange
var json = @"{
""Name"": ""John"",
""name"": ""Doe"",
""Age"": 30
}";

var element = JsonDocument.Parse(json).RootElement;

// Act
var dictionary = element.ToCaseInsensitiveDictionary();

// Assert
Assert.Equal(2, dictionary.Count);
Assert.True(dictionary.ContainsKey("name"));
Assert.True(dictionary.ContainsKey("age"));
Assert.Equal("Doe", dictionary["name"].GetString()); // The last occurrence should overwrite the previous one
Assert.Equal(30, dictionary["age"].GetInt32());
}
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace DaprExtensionTests.UnitTests.Services
namespace DaprExtensionTests.UnitTests.Utils
{
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Dapr;
Expand Down

0 comments on commit 35d6f1a

Please sign in to comment.