Skip to content

Commit 8a85664

Browse files
authored
Merge pull request #158 from Nex-Code/main
Expand arrays when dealing with parameters in RequestInformation
2 parents fd72483 + 132e958 commit 8a85664

File tree

4 files changed

+195
-14
lines changed

4 files changed

+195
-14
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.7.3] - 2023-11-30
11+
12+
### Changed
13+
14+
- Fixed an issue where arrays of non-string types passed into the query parameter were not being converted to strings leading to Invalid cast exceptions. [microsoft/kiota#3354](https://github.com/microsoft/kiota/issues/3354)
15+
1016
## [1.7.2] - 2023-11-14
1117

1218
### Added

Microsoft.Kiota.Abstractions.Tests/RequestInformationTests.cs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,167 @@ public void SetsEnumValuesInPathParameters()
502502
// Assert
503503
Assert.Equal("http://localhost/1,2", testRequest.URI.ToString());
504504
}
505+
506+
507+
[Fact]
508+
public void SetsIntValueInQueryParameters()
509+
{
510+
// Arrange
511+
var testRequest = new RequestInformation()
512+
{
513+
HttpMethod = Method.GET,
514+
UrlTemplate = "http://localhost/me{?item}"
515+
};
516+
// Act
517+
testRequest.AddQueryParameters(new GetQueryParameters { Item = 1 });
518+
// Assert
519+
Assert.Equal("http://localhost/me?item=1", testRequest.URI.ToString());
520+
}
521+
[Fact]
522+
public void SetsIntValuesInQueryParameters()
523+
{
524+
// Arrange
525+
var requestInfo = new RequestInformation()
526+
{
527+
HttpMethod = Method.GET,
528+
UrlTemplate = "http://localhost/me{?items}"
529+
};
530+
// Act
531+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object []{1,2}});
532+
// Assert
533+
Assert.Equal("http://localhost/me?items=1,2", requestInfo.URI.ToString());
534+
}
535+
536+
[Fact]
537+
public void SetsBooleanValuesInQueryParameters()
538+
{
539+
// Arrange
540+
var requestInfo = new RequestInformation()
541+
{
542+
HttpMethod = Method.GET,
543+
UrlTemplate = "http://localhost/me{?items}"
544+
};
545+
// Act
546+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object [] { true, false } });
547+
// Assert
548+
Assert.Equal("http://localhost/me?items=true,false", requestInfo.URI.ToString());
549+
}
550+
551+
[Fact]
552+
public void SetsDateTimeOffsetValuesInQueryParameters()
553+
{
554+
var requestInfo = new RequestInformation
555+
{
556+
HttpMethod = Method.GET,
557+
UrlTemplate = "http://localhost/me{?items}"
558+
};
559+
560+
// Act
561+
var dateTime1 = new DateTimeOffset(2022, 8, 1, 0, 0, 0, TimeSpan.Zero);
562+
var dateTime2 = new DateTimeOffset(2022, 8, 2, 0, 0, 0, TimeSpan.Zero);
563+
564+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { dateTime1, dateTime2 } });
565+
566+
// Assert
567+
Assert.Equal("http://localhost/me?items=2022-08-01T00%3A00%3A00.0000000%2B00%3A00,2022-08-02T00%3A00%3A00.0000000%2B00%3A00", requestInfo.URI.OriginalString);
568+
}
569+
[Fact]
570+
public void SetsDateTimeValuesInQueryParameters()
571+
{
572+
var requestInfo = new RequestInformation
573+
{
574+
HttpMethod = Method.GET,
575+
UrlTemplate = "http://localhost/me{?items}"
576+
};
577+
578+
// Act
579+
var dateTime1 = new DateTime(2022, 8, 1, 0, 0, 0);
580+
var dateTime2 = new DateTime(2022, 8, 2, 0, 0, 0);
581+
582+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { dateTime1, dateTime2 } });
583+
584+
// Assert
585+
Assert.Equal("http://localhost/me?items=2022-08-01T00%3A00%3A00.0000000,2022-08-02T00%3A00%3A00.0000000", requestInfo.URI.OriginalString);
586+
}
587+
588+
[Fact]
589+
public void SetsDateValuesInQueryParameters()
590+
{
591+
var requestInfo = new RequestInformation
592+
{
593+
HttpMethod = Method.GET,
594+
UrlTemplate = "http://localhost/me{?items}"
595+
};
596+
597+
// Act
598+
var date1 = new Date(2022, 8, 1);
599+
var date2 = new Date(2022, 8, 2);
600+
601+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { date1, date2 } });
602+
603+
// Assert
604+
Assert.Equal("http://localhost/me?items=2022-08-01,2022-08-02", requestInfo.URI.OriginalString);
605+
}
606+
607+
[Fact]
608+
public void SetsTimeValuesInQueryParameters()
609+
{
610+
var requestInfo = new RequestInformation
611+
{
612+
HttpMethod = Method.GET,
613+
UrlTemplate = "http://localhost/me{?items}"
614+
};
615+
616+
// Act
617+
var date1 = new Time(10,0,0);
618+
var date2 = new Time(11, 1, 1);
619+
620+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { date1, date2 } });
621+
622+
// Assert
623+
Assert.Equal("http://localhost/me?items=10%3A00%3A00,11%3A01%3A01", requestInfo.URI.OriginalString);
624+
}
625+
626+
[Fact]
627+
public void SetsGuidValuesInQueryParameters()
628+
{
629+
var requestInfo = new RequestInformation
630+
{
631+
HttpMethod = Method.GET,
632+
UrlTemplate = "http://localhost/me{?items}"
633+
};
634+
635+
// Act
636+
var g1 = Guid.Parse("55331110-6817-4A9B-83B2-57617E3E08E5");
637+
var g2 = Guid.Parse("482DFF4F-63D6-47F4-A88B-5CAEC03180D4");
638+
639+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { g1, g2 } });
640+
641+
// Assert
642+
Assert.Equal("http://localhost/me?items=55331110-6817-4a9b-83b2-57617e3e08e5,482dff4f-63d6-47f4-a88b-5caec03180d4", requestInfo.URI.OriginalString);
643+
}
644+
645+
646+
[Fact]
647+
public void DoesNotExpandSecondLayerArrays()
648+
{
649+
var requestInfo = new RequestInformation
650+
{
651+
HttpMethod = Method.GET,
652+
UrlTemplate = "http://localhost/me{?items}"
653+
};
654+
655+
// Act
656+
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[]{new int[]{1,2,3,4} } });
657+
// Assert
658+
Assert.Equal("http://localhost/me?items=System.Int32%5B%5D", requestInfo.URI.OriginalString);
659+
}
660+
661+
505662
}
506663

664+
665+
507666
/// <summary>The messages in a mailbox or folder. Read-only. Nullable.</summary>
508667
internal class GetQueryParameters
509668
{
@@ -533,5 +692,10 @@ internal class GetQueryParameters
533692
/// <summary>Which Dataset to use</summary>
534693
[QueryParameter("datasets")]
535694
public TestEnum[] DataSets { get; set; }
695+
696+
[QueryParameter("item")]
697+
public object Item { get; set; }
698+
[QueryParameter("items")]
699+
public object[] Items { get; set; }
536700
}
537701
}

src/Microsoft.Kiota.Abstractions.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<PackageProjectUrl>https://aka.ms/kiota/docs</PackageProjectUrl>
1515
<EmbedUntrackedSources>true</EmbedUntrackedSources>
1616
<Deterministic>true</Deterministic>
17-
<VersionPrefix>1.7.2</VersionPrefix>
17+
<VersionPrefix>1.7.3</VersionPrefix>
1818
<VersionSuffix></VersionSuffix>
1919
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
2020
<SignAssembly>false</SignAssembly>

src/RequestInformation.cs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
using System;
66
using System.Collections;
77
using System.Collections.Generic;
8+
using System.Collections.ObjectModel;
89
using System.Diagnostics;
910
using System.IO;
1011
using System.Linq;
1112
using System.Reflection;
13+
using System.Runtime.CompilerServices;
1214
using System.Runtime.Serialization;
1315
using Microsoft.Kiota.Abstractions.Extensions;
1416
using Microsoft.Kiota.Abstractions.Serialization;
@@ -89,14 +91,14 @@ public Uri URI
8991
var substitutions = new Dictionary<string, object>();
9092
foreach(var urlTemplateParameter in PathParameters)
9193
{
92-
substitutions.Add(urlTemplateParameter.Key, GetSanitizedValue(urlTemplateParameter.Value));
94+
substitutions.Add(urlTemplateParameter.Key, GetSanitizedValues(urlTemplateParameter.Value));
9395
}
9496

9597
foreach(var queryStringParameter in QueryParameters)
9698
{
9799
if(queryStringParameter.Value != null)
98100
{
99-
substitutions.Add(queryStringParameter.Key, GetSanitizedValue(queryStringParameter.Value));
101+
substitutions.Add(queryStringParameter.Key, GetSanitizedValues(queryStringParameter.Value));
100102
}
101103
}
102104

@@ -105,6 +107,12 @@ public Uri URI
105107
}
106108
}
107109

110+
private static object GetSanitizedValues(object value) => value switch
111+
{
112+
Array array => ExpandArray(array),
113+
_ => GetSanitizedValue(value),
114+
};
115+
108116
/// <summary>
109117
/// Sanitizes objects in order to appear appropiately in the URL
110118
/// </summary>
@@ -163,25 +171,28 @@ public void AddQueryParameters<T>(T source)
163171
!string.IsNullOrEmpty(x.Value.ToString()) && // no need to add an empty string value
164172
(x.Value is not ICollection collection || collection.Count > 0))) // no need to add empty collection
165173
{
166-
QueryParameters.AddOrReplace(property.Name!, ReplaceEnumValueByStringRepresentation(property.Value!));
174+
QueryParameters.AddOrReplace(property.Name!, property.Value!);
175+
}
176+
}
177+
178+
private static object ExpandArray(Array collection)
179+
{
180+
var passedArray = new string[collection.Length];
181+
for(var i = 0; i < collection.Length; i++)
182+
{
183+
passedArray[i] = GetSanitizedValue(collection.GetValue(i)!).ToString()!;
167184
}
185+
return passedArray;
168186
}
187+
169188
private static object ReplaceEnumValueByStringRepresentation(object source)
170189
{
171190
if(source is Enum enumValue && GetEnumName(enumValue) is string enumValueName)
172191
{
173192
return enumValueName;
174193
}
175-
else if(source is Array collection && collection.Length > 0 && collection.GetValue(0) is Enum)
176-
{
177-
var passedArray = new string[collection.Length];
178-
for(var i = 0; i < collection.Length; i++)
179-
{// this is ugly but necessary due to covariance limitations with pattern matching
180-
passedArray[i] = GetEnumName((Enum)collection.GetValue(i)!)!;
181-
}
182-
return passedArray;
183-
}
184-
else return source;
194+
195+
return source;
185196
}
186197
#if NET5_0_OR_GREATER
187198
private static string? GetEnumName<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(T value) where T : Enum

0 commit comments

Comments
 (0)