Skip to content

Commit

Permalink
Merge pull request #158 from Nex-Code/main
Browse files Browse the repository at this point in the history
Expand arrays when dealing with parameters in RequestInformation
  • Loading branch information
andrueastman authored Dec 4, 2023
2 parents fd72483 + 132e958 commit 8a85664
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 14 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.7.3] - 2023-11-30

### Changed

- 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)

## [1.7.2] - 2023-11-14

### Added
Expand Down
164 changes: 164 additions & 0 deletions Microsoft.Kiota.Abstractions.Tests/RequestInformationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,167 @@ public void SetsEnumValuesInPathParameters()
// Assert
Assert.Equal("http://localhost/1,2", testRequest.URI.ToString());
}


[Fact]
public void SetsIntValueInQueryParameters()
{
// Arrange
var testRequest = new RequestInformation()
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?item}"
};
// Act
testRequest.AddQueryParameters(new GetQueryParameters { Item = 1 });
// Assert
Assert.Equal("http://localhost/me?item=1", testRequest.URI.ToString());
}
[Fact]
public void SetsIntValuesInQueryParameters()
{
// Arrange
var requestInfo = new RequestInformation()
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};
// Act
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object []{1,2}});
// Assert
Assert.Equal("http://localhost/me?items=1,2", requestInfo.URI.ToString());
}

[Fact]
public void SetsBooleanValuesInQueryParameters()
{
// Arrange
var requestInfo = new RequestInformation()
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};
// Act
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object [] { true, false } });
// Assert
Assert.Equal("http://localhost/me?items=true,false", requestInfo.URI.ToString());
}

[Fact]
public void SetsDateTimeOffsetValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
var dateTime1 = new DateTimeOffset(2022, 8, 1, 0, 0, 0, TimeSpan.Zero);
var dateTime2 = new DateTimeOffset(2022, 8, 2, 0, 0, 0, TimeSpan.Zero);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { dateTime1, dateTime2 } });

// Assert
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);
}
[Fact]
public void SetsDateTimeValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
var dateTime1 = new DateTime(2022, 8, 1, 0, 0, 0);
var dateTime2 = new DateTime(2022, 8, 2, 0, 0, 0);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { dateTime1, dateTime2 } });

// Assert
Assert.Equal("http://localhost/me?items=2022-08-01T00%3A00%3A00.0000000,2022-08-02T00%3A00%3A00.0000000", requestInfo.URI.OriginalString);
}

[Fact]
public void SetsDateValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
var date1 = new Date(2022, 8, 1);
var date2 = new Date(2022, 8, 2);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { date1, date2 } });

// Assert
Assert.Equal("http://localhost/me?items=2022-08-01,2022-08-02", requestInfo.URI.OriginalString);
}

[Fact]
public void SetsTimeValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
var date1 = new Time(10,0,0);
var date2 = new Time(11, 1, 1);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { date1, date2 } });

// Assert
Assert.Equal("http://localhost/me?items=10%3A00%3A00,11%3A01%3A01", requestInfo.URI.OriginalString);
}

[Fact]
public void SetsGuidValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
var g1 = Guid.Parse("55331110-6817-4A9B-83B2-57617E3E08E5");
var g2 = Guid.Parse("482DFF4F-63D6-47F4-A88B-5CAEC03180D4");

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { g1, g2 } });

// Assert
Assert.Equal("http://localhost/me?items=55331110-6817-4a9b-83b2-57617e3e08e5,482dff4f-63d6-47f4-a88b-5caec03180d4", requestInfo.URI.OriginalString);
}


[Fact]
public void DoesNotExpandSecondLayerArrays()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[]{new int[]{1,2,3,4} } });
// Assert
Assert.Equal("http://localhost/me?items=System.Int32%5B%5D", requestInfo.URI.OriginalString);
}


}



/// <summary>The messages in a mailbox or folder. Read-only. Nullable.</summary>
internal class GetQueryParameters
{
Expand Down Expand Up @@ -533,5 +692,10 @@ internal class GetQueryParameters
/// <summary>Which Dataset to use</summary>
[QueryParameter("datasets")]
public TestEnum[] DataSets { get; set; }

[QueryParameter("item")]
public object Item { get; set; }
[QueryParameter("items")]
public object[] Items { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.Kiota.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageProjectUrl>https://aka.ms/kiota/docs</PackageProjectUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<Deterministic>true</Deterministic>
<VersionPrefix>1.7.2</VersionPrefix>
<VersionPrefix>1.7.3</VersionPrefix>
<VersionSuffix></VersionSuffix>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
Expand Down
37 changes: 24 additions & 13 deletions src/RequestInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
Expand Down Expand Up @@ -89,14 +91,14 @@ public Uri URI
var substitutions = new Dictionary<string, object>();
foreach(var urlTemplateParameter in PathParameters)
{
substitutions.Add(urlTemplateParameter.Key, GetSanitizedValue(urlTemplateParameter.Value));
substitutions.Add(urlTemplateParameter.Key, GetSanitizedValues(urlTemplateParameter.Value));
}

foreach(var queryStringParameter in QueryParameters)
{
if(queryStringParameter.Value != null)
{
substitutions.Add(queryStringParameter.Key, GetSanitizedValue(queryStringParameter.Value));
substitutions.Add(queryStringParameter.Key, GetSanitizedValues(queryStringParameter.Value));
}
}

Expand All @@ -105,6 +107,12 @@ public Uri URI
}
}

private static object GetSanitizedValues(object value) => value switch
{
Array array => ExpandArray(array),
_ => GetSanitizedValue(value),
};

/// <summary>
/// Sanitizes objects in order to appear appropiately in the URL
/// </summary>
Expand Down Expand Up @@ -163,25 +171,28 @@ public void AddQueryParameters<T>(T source)
!string.IsNullOrEmpty(x.Value.ToString()) && // no need to add an empty string value
(x.Value is not ICollection collection || collection.Count > 0))) // no need to add empty collection
{
QueryParameters.AddOrReplace(property.Name!, ReplaceEnumValueByStringRepresentation(property.Value!));
QueryParameters.AddOrReplace(property.Name!, property.Value!);
}
}

private static object ExpandArray(Array collection)
{
var passedArray = new string[collection.Length];
for(var i = 0; i < collection.Length; i++)
{
passedArray[i] = GetSanitizedValue(collection.GetValue(i)!).ToString()!;
}
return passedArray;
}

private static object ReplaceEnumValueByStringRepresentation(object source)
{
if(source is Enum enumValue && GetEnumName(enumValue) is string enumValueName)
{
return enumValueName;
}
else if(source is Array collection && collection.Length > 0 && collection.GetValue(0) is Enum)
{
var passedArray = new string[collection.Length];
for(var i = 0; i < collection.Length; i++)
{// this is ugly but necessary due to covariance limitations with pattern matching
passedArray[i] = GetEnumName((Enum)collection.GetValue(i)!)!;
}
return passedArray;
}
else return source;

return source;
}
#if NET5_0_OR_GREATER
private static string? GetEnumName<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(T value) where T : Enum
Expand Down

0 comments on commit 8a85664

Please sign in to comment.