C
C#•3y ago
malkav

Azure function returning error

Here is the error I get from the Azure function test:
2022-09-21T14:04:51.850 [Error] Executed 'MergeSingleAsync' (Failed, Id=f50af7c5-6b25-4c1a-ab39-7f8aff066255, Duration=2ms)The best overloaded method match for 'string.this[int]' has some invalid arguments
2022-09-21T14:04:51.850 [Error] Executed 'MergeSingleAsync' (Failed, Id=f50af7c5-6b25-4c1a-ab39-7f8aff066255, Duration=2ms)The best overloaded method match for 'string.this[int]' has some invalid arguments
Here is my Azure function (in two or three messages because of its size)
public static class MergeSingleAsync
{
[FunctionName("MergeSingleAsync")]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
Dictionary<string, dynamic> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(data["main_object"]);
Dictionary<string, dynamic> secondaryObject =
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(data["secondary_object"]);
dynamic matching = data["matching_property"];
string[] mergingProperties = data["merge_properties"] == null
? Array.Empty<string>()
: (string[])JsonConvert.DeserializeObject<string[]>(data.merge_properties);
if (!mainObject.ContainsKey(matching) && !secondaryObject.ContainsKey(matching) &&
mainObject[matching] != secondaryObject[matching])
throw new($"The matching property: {matching} did not match in both objects provided to the function");
return mergingProperties.Length == 0
? MergeAll(mainObject, secondaryObject)
: MergeSpecific(mainObject, secondaryObject, mergingProperties);
}
public static class MergeSingleAsync
{
[FunctionName("MergeSingleAsync")]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
Dictionary<string, dynamic> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(data["main_object"]);
Dictionary<string, dynamic> secondaryObject =
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(data["secondary_object"]);
dynamic matching = data["matching_property"];
string[] mergingProperties = data["merge_properties"] == null
? Array.Empty<string>()
: (string[])JsonConvert.DeserializeObject<string[]>(data.merge_properties);
if (!mainObject.ContainsKey(matching) && !secondaryObject.ContainsKey(matching) &&
mainObject[matching] != secondaryObject[matching])
throw new($"The matching property: {matching} did not match in both objects provided to the function");
return mergingProperties.Length == 0
? MergeAll(mainObject, secondaryObject)
: MergeSpecific(mainObject, secondaryObject, mergingProperties);
}
36 Replies
malkav
malkavOP•3y ago
and here is the first of the two methods I created to merge the JSON objects:
private static IActionResult MergeSpecific(IDictionary<string, dynamic> mainObject,
Dictionary<string, dynamic> secondaryObject, string[] mergingProperties)
{
foreach (string item in secondaryObject.Keys.Where(item => !mainObject.ContainsKey(item)))
{
if (!mergingProperties.Contains(item)) continue;
mainObject.Add(item, secondaryObject[item]);
}

return new OkObjectResult(JsonConvert.SerializeObject(mainObject));
}
private static IActionResult MergeSpecific(IDictionary<string, dynamic> mainObject,
Dictionary<string, dynamic> secondaryObject, string[] mergingProperties)
{
foreach (string item in secondaryObject.Keys.Where(item => !mainObject.ContainsKey(item)))
{
if (!mergingProperties.Contains(item)) continue;
mainObject.Add(item, secondaryObject[item]);
}

return new OkObjectResult(JsonConvert.SerializeObject(mainObject));
}
and the second:
private static IActionResult MergeAll(IDictionary<string, object> mainObject,
Dictionary<string, object> secondaryObject)
{
foreach (string item in secondaryObject.Keys.Where(item => !mainObject.ContainsKey(item)))
{
mainObject.Add(item, secondaryObject[item]);
}

return new OkObjectResult(JsonConvert.SerializeObject(mainObject));
}
private static IActionResult MergeAll(IDictionary<string, object> mainObject,
Dictionary<string, object> secondaryObject)
{
foreach (string item in secondaryObject.Keys.Where(item => !mainObject.ContainsKey(item)))
{
mainObject.Add(item, secondaryObject[item]);
}

return new OkObjectResult(JsonConvert.SerializeObject(mainObject));
}
Angius
Angius•3y ago
dynamic Scrap the code
malkav
malkavOP•3y ago
say what now?
Angius
Angius•3y ago
There's no reason to ever use dynamic unless you're doing some weird interop Frankly, it should be hidden behind a compiler flag or something
malkav
malkavOP•3y ago
I am getting a JSON from a user with strings as keys, but the values can literally be anything. So dynamic sounded like the best option... what else would I do.. Also instead of coming at me with "scrap the code", you could've started the conversation different... now it feels more like an attack than actual help...
Yawnder
Yawnder•3y ago
JsonToken or JToken depending on which library you use.
malkav
malkavOP•3y ago
Newtonsoft.Json is the lib I'm using
Yawnder
Yawnder•3y ago
Then if you can't create a model closer to what they're sending, use JToken imo.
malkav
malkavOP•3y ago
I'll use JsonToken instead then. Sure.. though this is already a lot less "provocative" than earlier comments 😅
Yawnder
Yawnder•3y ago
For your issue at hand, I'm trying to find where you call MergeSingleAsync.
Angius
Angius•3y ago
Sorry for that, dynamic, ArrayList, and the like, create a very visceral response in me lol
Yawnder
Yawnder•3y ago
Not just in you. I generally just ignore anyone talking about $dynamic
MODiX
MODiX•3y ago
please no
malkav
malkavOP•3y ago
in the return of the first bit of code return mergingProperties.Length == 0 ? MergeAll(mainObject, secondaryObject) : MergeSpecific(mainObject, secondaryObject, mergingProperties); I understand the response, don't get me wrong. I've got the same response when I see it in dart or any language for that matter. But this is my very first setup of the program, after which I would clean such things as dynamic up into actual types and such... I needed help with an error I didn't understand, not the dynamic part 😅 now it just felt like a huge attack instead of the help I asked for. But I'm being helped now, which is already a huge relief!
Yawnder
Yawnder•3y ago
Oh, it's the call to the AzureFunction itself that fails, not within the method?
malkav
malkavOP•3y ago
Oh, right. I read you wrong. yes the MergeSingleAsync() is the Azure Function itself
Yawnder
Yawnder•3y ago
So what is the actual exception? It's the call itself?
malkav
malkavOP•3y ago
all the way at the top is the exception I got in the filesystem logs
2022-09-21T14:04:51.850 [Error] Executed 'MergeSingleAsync' (Failed, Id=f50af7c5-6b25-4c1a-ab39-7f8aff066255, Duration=2ms)The best overloaded method match for 'string.this[int]' has some invalid arguments
2022-09-21T14:04:51.850 [Error] Executed 'MergeSingleAsync' (Failed, Id=f50af7c5-6b25-4c1a-ab39-7f8aff066255, Duration=2ms)The best overloaded method match for 'string.this[int]' has some invalid arguments
However now I'm trying to remove the dynamic parts I'm getting issues with the way I am getting data from the req.Body Currently I'm trying this:
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var data = JsonConvert.DeserializeObject(requestBody);
Dictionary<string, JsonToken> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, JsonToken>>(data["main_object"]);
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var data = JsonConvert.DeserializeObject(requestBody);
Dictionary<string, JsonToken> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, JsonToken>>(data["main_object"]);
But the ["main_object"] part gets the following error: Cannot apply indexing to an expression of type 'object' wait, I have an idea for the latter error
Yawnder
Yawnder•3y ago
The error you have listed there doesn't help much. It's either the way you're calling that AzFunction/Method or somewhere within that's not shown. When you run it locally where does it break?
malkav
malkavOP•3y ago
sadly I haven't been able to figure out how to run the azure function locally since I'm trying to run it via Rider, and I keep getting this weird error on that part.. something along the lines of:
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\'.
Failed to run as a self-contained app.
- The application was run as a self-contained app because 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\CloudShift.MergeObjects.runtimeconfig.json' was not found.
- If this should be a framework-dependent app, add the 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\CloudShift.MergeObjects.runtimeconfig.json' file and specify the appropriate f
ramework.
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\'.
Failed to run as a self-contained app.
- The application was run as a self-contained app because 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\CloudShift.MergeObjects.runtimeconfig.json' was not found.
- If this should be a framework-dependent app, add the 'C:\Users\{user}\Projects\Company.MergeObjects\Company.MergeObjects\bin\Debug\net6.0\CloudShift.MergeObjects.runtimeconfig.json' file and specify the appropriate f
ramework.
Yawnder
Yawnder•3y ago
No idea how, sorry. I'm on VS so I just press F5.
malkav
malkavOP•3y ago
I'm trying to call the function in the portal with this as the body:
{
"main_object": "{ \"name\": \"NamingPerson\", \"id\": \"123\" }",
"secondary_object": "{ \"phone\": \"1234567\", \"id\": \"123\" }",
"matching_property": "id",
"merge_property": ["phone"],
}
{
"main_object": "{ \"name\": \"NamingPerson\", \"id\": \"123\" }",
"secondary_object": "{ \"phone\": \"1234567\", \"id\": \"123\" }",
"matching_property": "id",
"merge_property": ["phone"],
}
Cisien
Cisien•3y ago
You want JToken for newtonsoft. JsonToken is for System.Text.Json
malkav
malkavOP•3y ago
Ah, okay. I'll use JToken
Cisien
Cisien•3y ago
Instead of serializing, use JObject.Parse
Yawnder
Yawnder•3y ago
Can you show the window (with the url it's calling, but without the key) you're calling from?
malkav
malkavOP•3y ago
sure, give me a sec
malkav
malkavOP•3y ago
malkav
malkavOP•3y ago
Yawnder
Yawnder•3y ago
I feel like in this message, 2022-09-21T14:04:51.850 [Error] Executed 'MergeSingleAsync' (Failed, Id=f50af7c5-6b25-4c1a-ab39-7f8aff066255, Duration=2ms)The best overloaded method match for 'string.this[int]' has some invalid arguments, the string.this[int] is in reference to the POST, and it can't find a method that fits within your dll. Could it be that your DI isn't setup properly? I'm just throwing an idea, but I'm unsure since you can't run it locally.
malkav
malkavOP•3y ago
I'm mainly getting now "Could not cast or convert from System.String to My.Namespace.Inputs" Here's my new Azure Function with dynamic removed:
[FunctionName("MergeSingleAsync")]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Inputs data = JsonConvert.DeserializeObject<Inputs>(requestBody);
// The main object in which we will merge properties
Dictionary<string, JToken> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, JToken>>(data.MainObject);
// The secondary object of which we will merge properties into mainObject
Dictionary<string, JToken> secondaryObject =
JsonConvert.DeserializeObject<Dictionary<string, JToken>>(data.SecondaryObject);
// The property that should match in both objects
dynamic matching = data.MatchingProperty;
// The Array of string items that are the keys to merge from secondaryObject to mainObject
string[] mergingProperties = data.MergeProperties;
if (!mainObject.ContainsKey(matching) && !secondaryObject.ContainsKey(matching) &&
mainObject[matching] != secondaryObject[matching])
throw new($"The matching property: {matching} did not match in both objects provided to the function");
return mergingProperties.Length == 0
? MergeAll(mainObject, secondaryObject)
: MergeSpecific(mainObject, secondaryObject, mergingProperties);
}
[FunctionName("MergeSingleAsync")]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Inputs data = JsonConvert.DeserializeObject<Inputs>(requestBody);
// The main object in which we will merge properties
Dictionary<string, JToken> mainObject =
JsonConvert.DeserializeObject<Dictionary<string, JToken>>(data.MainObject);
// The secondary object of which we will merge properties into mainObject
Dictionary<string, JToken> secondaryObject =
JsonConvert.DeserializeObject<Dictionary<string, JToken>>(data.SecondaryObject);
// The property that should match in both objects
dynamic matching = data.MatchingProperty;
// The Array of string items that are the keys to merge from secondaryObject to mainObject
string[] mergingProperties = data.MergeProperties;
if (!mainObject.ContainsKey(matching) && !secondaryObject.ContainsKey(matching) &&
mainObject[matching] != secondaryObject[matching])
throw new($"The matching property: {matching} did not match in both objects provided to the function");
return mergingProperties.Length == 0
? MergeAll(mainObject, secondaryObject)
: MergeSpecific(mainObject, secondaryObject, mergingProperties);
}
with the Model for the input:
public class Inputs
{
[JsonProperty("main_object")] public string MainObject { get; set; }
[JsonProperty("secondary_object")] public string SecondaryObject { get; set; }
[JsonProperty("matching_property")] public JToken MatchingProperty { get; set; }

[JsonProperty("merge_properties")] public string[] MergeProperties { get; set; } = Array.Empty<string>();
}
public class Inputs
{
[JsonProperty("main_object")] public string MainObject { get; set; }
[JsonProperty("secondary_object")] public string SecondaryObject { get; set; }
[JsonProperty("matching_property")] public JToken MatchingProperty { get; set; }

[JsonProperty("merge_properties")] public string[] MergeProperties { get; set; } = Array.Empty<string>();
}
and the req.Body I'm using:
{
"main_object": "{ \"name\": \"Soufian\", \"id\": \"123\" }",
"secondary_object": "{ \"phone\": \"1234567\", \"id\": \"123\" }",
"matching_property": "id",
"merge_properties": ["phone"],
}
{
"main_object": "{ \"name\": \"Soufian\", \"id\": \"123\" }",
"secondary_object": "{ \"phone\": \"1234567\", \"id\": \"123\" }",
"matching_property": "id",
"merge_properties": ["phone"],
}
Yawnder
Yawnder•3y ago
(you still have dynamic in there btw)
malkav
malkavOP•3y ago
Oh I do o.O OOps, that should also be JToken sorry 😅 consider that edited
Yawnder
Yawnder•3y ago
But if you get that message, it's running or it's when building?
malkav
malkavOP•3y ago
it should be running.. imma publish again to the dev function i created, and wait a few minutes before testing again..
Cisien
Cisien•3y ago
your request body is 4 properties of strings, not 4 properties of json objects if you want to turn those strings into things your app can deal with, you need to further process them (JObject.Parse, for example)

Did you find this page helpful?