diff --git a/clean-bin-and-obj.bat b/clean-bin-and-obj.bat new file mode 100644 index 0000000..f0b158d --- /dev/null +++ b/clean-bin-and-obj.bat @@ -0,0 +1,15 @@ +@Echo Off +FOR /d /r .\ %%d IN (*) DO ( + @IF EXIST "%%d" ( + pushd %%d + FOR /d /r %%t IN (bin\, obj\) DO ( + @IF EXIST "%%t" ( + ECHO "Removing %%t" + rd /s /q "%%t" + ) + ) + popd + ) +) + +pause \ No newline at end of file diff --git a/src/Geo.ArcGIS/Models/Parameters/GeocodingParameters.cs b/src/Geo.ArcGIS/Models/Parameters/GeocodingParameters.cs index da8483e..1f29650 100644 --- a/src/Geo.ArcGIS/Models/Parameters/GeocodingParameters.cs +++ b/src/Geo.ArcGIS/Models/Parameters/GeocodingParameters.cs @@ -12,7 +12,7 @@ namespace Geo.ArcGIS.Models.Parameters /// /// A parameters object for the geocoding ArcGIS request. /// - public class GeocodingParameters : IClientCredentialsParameters + public class GeocodingParameters : IClientCredentialsParameters, IAdditionalParameters { /// /// Gets a list of address attributes. @@ -85,5 +85,8 @@ public class GeocodingParameters : IClientCredentialsParameters /// public string ClientSecret { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.ArcGIS/Models/Parameters/StorageParameters.cs b/src/Geo.ArcGIS/Models/Parameters/StorageParameters.cs index 9a73f06..a2b7306 100644 --- a/src/Geo.ArcGIS/Models/Parameters/StorageParameters.cs +++ b/src/Geo.ArcGIS/Models/Parameters/StorageParameters.cs @@ -5,10 +5,12 @@ namespace Geo.ArcGIS.Models.Parameters { + using System.Collections.Generic; + /// /// A parameters object for the storage flag information in ArcGIS request. /// - public class StorageParameters + public class StorageParameters : IAdditionalParameters { /// /// Gets or sets a value indicating whether the results of the operation will be persisted. @@ -31,5 +33,8 @@ public class StorageParameters /// (https://developers.arcgis.com/rest/geocode/api-reference/geocoding-free-vs-paid.htm). /// public bool ForStorage { get; set; } = false; + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.ArcGIS/Models/Parameters/SuggestParameters.cs b/src/Geo.ArcGIS/Models/Parameters/SuggestParameters.cs index 9e88127..6c7bc80 100644 --- a/src/Geo.ArcGIS/Models/Parameters/SuggestParameters.cs +++ b/src/Geo.ArcGIS/Models/Parameters/SuggestParameters.cs @@ -13,7 +13,7 @@ namespace Geo.ArcGIS.Models.Parameters /// /// A parameters object for the suggest ArcGIS request. /// - public class SuggestParameters + public class SuggestParameters : IAdditionalParameters { /// /// Gets or sets the input text entered by a user, which is used by the suggest operation to generate a list of possible matches. @@ -65,5 +65,8 @@ public class SuggestParameters /// The default value is postal city. /// public PreferredLabelValue PreferredLabelValue { get; set; } = PreferredLabelValue.PostalCity; + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.ArcGIS/Services/ArcGISGeocoding.cs b/src/Geo.ArcGIS/Services/ArcGISGeocoding.cs index c113377..aaf79fc 100644 --- a/src/Geo.ArcGIS/Services/ArcGISGeocoding.cs +++ b/src/Geo.ArcGIS/Services/ArcGISGeocoding.cs @@ -420,6 +420,7 @@ internal async Task BuildAddressCandidateRequest(AddressCandidateParameters AddStorageParameter(parameters, ref query); query = await AddArcGISToken(parameters, query, cancellationToken).ConfigureAwait(false); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -597,6 +598,7 @@ internal async Task BuildPlaceCandidateRequest(PlaceCandidateParameters par AddStorageParameter(parameters, ref query); query = await AddArcGISToken(parameters, query, cancellationToken).ConfigureAwait(false); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -686,6 +688,8 @@ internal Task BuildSuggestRequest(SuggestParameters parameters, Cancellatio _logger.ArcGISWarning(Resources.Services.ArcGISGeocoding.Invalid_Preferred_Label_Value); } + query = query.AddAdditionalParameters(parameters); + uriBuilder.AddQuery(query); return Task.FromResult(uriBuilder.Uri); @@ -765,6 +769,7 @@ internal async Task BuildReverseGeocodingRequest(ReverseGeocodingParameters AddStorageParameter(parameters, ref query); query = await AddArcGISToken(parameters, query, cancellationToken).ConfigureAwait(false); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -884,6 +889,7 @@ internal async Task BuildGeocodingRequest(GeocodingParameters parameters, C } query = await AddArcGISToken(parameters, query, cancellationToken).ConfigureAwait(false); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.Bing/Models/Parameters/BaseParameters.cs b/src/Geo.Bing/Models/Parameters/BaseParameters.cs index dd57fca..769d124 100644 --- a/src/Geo.Bing/Models/Parameters/BaseParameters.cs +++ b/src/Geo.Bing/Models/Parameters/BaseParameters.cs @@ -5,12 +5,13 @@ namespace Geo.Bing.Models.Parameters { + using System.Collections.Generic; using System.Globalization; /// /// Base parameters across all Bing geocoding APIs. /// - public class BaseParameters + public class BaseParameters : IAdditionalParameters { /// /// Gets or sets a value indicating whether or not to include the neighbourhood information. @@ -34,5 +35,8 @@ public class BaseParameters /// Gets or sets the culture to use for the request. /// public CultureInfo Culture { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Bing/Services/BingGeocoding.cs b/src/Geo.Bing/Services/BingGeocoding.cs index bc8d3ca..8e67ef8 100644 --- a/src/Geo.Bing/Services/BingGeocoding.cs +++ b/src/Geo.Bing/Services/BingGeocoding.cs @@ -126,6 +126,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) BuildLimitedResultQuery(parameters, ref query); AddBingKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -197,6 +198,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) BuildBaseQuery(parameters, ref query); AddBingKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -272,6 +274,7 @@ internal Uri BuildAddressGeocodingRequest(AddressGeocodingParameters parameters) BuildLimitedResultQuery(parameters, ref query); AddBingKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.Core/Abstractions/IAdditionalParameters.cs b/src/Geo.Core/Abstractions/IAdditionalParameters.cs new file mode 100644 index 0000000..58e07ce --- /dev/null +++ b/src/Geo.Core/Abstractions/IAdditionalParameters.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Geo.NET. +// Licensed under the MIT license. See the LICENSE file in the solution root for full license information. +// + +namespace Geo +{ + using System.Collections.Generic; + + /// + /// Parameters that allow additional key/value pairs to be appended to the request query string. + /// + public interface IAdditionalParameters + { + /// + /// Gets the additional key/value pairs to be appended to the request query string. + /// + IDictionary AdditionalParameters { get; } + } +} diff --git a/src/Geo.Core/Extensions/QueryStringExtensions.cs b/src/Geo.Core/Extensions/QueryStringExtensions.cs new file mode 100644 index 0000000..6b7ad25 --- /dev/null +++ b/src/Geo.Core/Extensions/QueryStringExtensions.cs @@ -0,0 +1,42 @@ +// +// Copyright (c) Geo.NET. +// Licensed under the MIT license. See the LICENSE file in the solution root for full license information. +// + +namespace Geo.Core.Extensions +{ + using Geo; + + /// + /// Extension methods on the struct. + /// + public static class QueryStringExtensions + { + /// + /// Adds any additional parameters from an instance to the . + /// Entries with a null value are skipped. + /// + /// The to add to. + /// The to read additional key/value pairs from. + /// The with the additional parameters appended. + public static QueryString AddAdditionalParameters(this QueryString query, IAdditionalParameters parameters) + { + if (parameters?.AdditionalParameters == null) + { + return query; + } + + foreach (var kvp in parameters.AdditionalParameters) + { + if (kvp.Value == null) + { + continue; + } + + query = query.Add(kvp.Key, kvp.Value); + } + + return query; + } + } +} diff --git a/src/Geo.Google/Models/Parameters/BaseParameters.cs b/src/Geo.Google/Models/Parameters/BaseParameters.cs index 6001dbe..b023520 100644 --- a/src/Geo.Google/Models/Parameters/BaseParameters.cs +++ b/src/Geo.Google/Models/Parameters/BaseParameters.cs @@ -5,16 +5,20 @@ namespace Geo.Google.Models.Parameters { + using System.Collections.Generic; using System.Globalization; /// /// The base parameters shared across all requests. /// - public class BaseParameters + public class BaseParameters : IAdditionalParameters { /// /// Gets or sets the language in which to return results. /// public CultureInfo Language { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Google/Services/GoogleGeocoding.cs b/src/Geo.Google/Services/GoogleGeocoding.cs index 000ed1a..159d050 100644 --- a/src/Geo.Google/Services/GoogleGeocoding.cs +++ b/src/Geo.Google/Services/GoogleGeocoding.cs @@ -235,6 +235,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -303,6 +304,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -371,6 +373,7 @@ internal Uri BuildFindPlaceRequest(FindPlacesParameters parameters) AddBaseParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -439,6 +442,7 @@ internal Uri BuildNearbySearchRequest(NearbySearchParameters parameters) AddBaseSearchParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -476,6 +480,7 @@ internal Uri BuildTextSearchRequest(TextSearchParameters parameters) AddBaseSearchParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -531,6 +536,7 @@ internal Uri BuildDetailsRequest(DetailsParameters parameters) AddBaseParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -597,6 +603,7 @@ internal Uri BuildPlaceAutocompleteRequest(PlacesAutocompleteParameters paramete AddAutocompleteParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -623,6 +630,7 @@ internal Uri BuildQueryAutocompleteRequest(QueryAutocompleteParameters parameter AddAutocompleteParameters(parameters, ref query); AddGoogleKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.Here/Models/Parameters/BaseParameters.cs b/src/Geo.Here/Models/Parameters/BaseParameters.cs index 9947342..8385d4f 100644 --- a/src/Geo.Here/Models/Parameters/BaseParameters.cs +++ b/src/Geo.Here/Models/Parameters/BaseParameters.cs @@ -11,7 +11,7 @@ namespace Geo.Here.Models.Parameters /// /// The base parameters that are used with all HERE requests. /// - public class BaseParameters + public class BaseParameters : IAdditionalParameters { /// /// Gets or sets the language to be used for result rendering from a list of BCP47 compliant Language Codes. @@ -36,5 +36,8 @@ public class BaseParameters /// /// public IList Show { get; } = new List(); + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Here/Services/HereGeocoding.cs b/src/Geo.Here/Services/HereGeocoding.cs index c2304ae..d06fc1c 100644 --- a/src/Geo.Here/Services/HereGeocoding.cs +++ b/src/Geo.Here/Services/HereGeocoding.cs @@ -197,6 +197,7 @@ internal Uri BuildGeocodingRequest(GeocodeParameters parameters) AddLocatingParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -242,6 +243,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodeParameters parameters) AddLocatingParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -270,6 +272,7 @@ internal Uri BuildDiscoverRequest(DiscoverParameters parameters) AddBoundingParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -307,6 +310,7 @@ internal Uri BuildAutosuggestRequest(AutosuggestParameters parameters) AddBoundingParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -351,6 +355,7 @@ internal Uri BuildBrowseRequest(BrowseParameters parameters) AddBoundingParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -379,6 +384,7 @@ internal Uri BuildLookupRequest(LookupParameters parameters) AddBaseParameters(parameters, ref query); AddHereKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.MapBox/Models/Parameters/BaseParameters.cs b/src/Geo.MapBox/Models/Parameters/BaseParameters.cs index 3f3bc79..e5f5f57 100644 --- a/src/Geo.MapBox/Models/Parameters/BaseParameters.cs +++ b/src/Geo.MapBox/Models/Parameters/BaseParameters.cs @@ -12,7 +12,7 @@ namespace Geo.MapBox.Models.Parameters /// /// The parameters possible to use for all requests. /// - public class BaseParameters + public class BaseParameters : IAdditionalParameters { /// /// Gets or sets the type of endpoint to call. @@ -52,5 +52,8 @@ public class BaseParameters /// Available worldviews are: ar,cn,in,jp,ma,ru,tr,us. If worldview is not set, the us worldview boundaries are returned by default. /// public string Worldview { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.MapBox/Services/MapBoxGeocoding.cs b/src/Geo.MapBox/Services/MapBoxGeocoding.cs index 9ed5c8a..1e356b9 100644 --- a/src/Geo.MapBox/Services/MapBoxGeocoding.cs +++ b/src/Geo.MapBox/Services/MapBoxGeocoding.cs @@ -149,6 +149,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddMapBoxKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -179,6 +180,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddMapBoxKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.MapQuest/Models/Parameters/BaseParameters.cs b/src/Geo.MapQuest/Models/Parameters/BaseParameters.cs index b7f4cfa..812b307 100644 --- a/src/Geo.MapQuest/Models/Parameters/BaseParameters.cs +++ b/src/Geo.MapQuest/Models/Parameters/BaseParameters.cs @@ -5,15 +5,20 @@ namespace Geo.MapQuest.Models.Parameters { + using System.Collections.Generic; + /// /// The base parameters used across all requests. /// - public class BaseParameters + public class BaseParameters : IAdditionalParameters { /// /// Gets or sets a value indicating whether a URL to a static map thumbnail image for a location being geocoded should be returned. /// Default is true. /// public bool IncludeThumbMaps { get; set; } = true; + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.MapQuest/Services/MapQuestGeocoding.cs b/src/Geo.MapQuest/Services/MapQuestGeocoding.cs index 913762a..d9eabd8 100644 --- a/src/Geo.MapQuest/Services/MapQuestGeocoding.cs +++ b/src/Geo.MapQuest/Services/MapQuestGeocoding.cs @@ -175,6 +175,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddMapQuestKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -211,6 +212,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) AddBaseParameters(parameters, ref query); AddMapQuestKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.Positionstack/Models/Parameters/GeocodingParameters.cs b/src/Geo.Positionstack/Models/Parameters/GeocodingParameters.cs index 4ee2df7..071f1ac 100644 --- a/src/Geo.Positionstack/Models/Parameters/GeocodingParameters.cs +++ b/src/Geo.Positionstack/Models/Parameters/GeocodingParameters.cs @@ -11,7 +11,7 @@ namespace Geo.Positionstack.Models.Parameters /// /// The parameters possible to use during a geocoding request. /// - public class GeocodingParameters : ILocationGeocodeParameters, IFilterGeocodeParameters, IKeyParameters + public class GeocodingParameters : ILocationGeocodeParameters, IFilterGeocodeParameters, IKeyParameters, IAdditionalParameters { /// /// Gets or sets the address to geocode. @@ -47,5 +47,8 @@ public class GeocodingParameters : ILocationGeocodeParameters, IFilterGeocodePar /// public string Key { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Positionstack/Models/Parameters/ReverseGeocodingParameters.cs b/src/Geo.Positionstack/Models/Parameters/ReverseGeocodingParameters.cs index 8229f8b..439356c 100644 --- a/src/Geo.Positionstack/Models/Parameters/ReverseGeocodingParameters.cs +++ b/src/Geo.Positionstack/Models/Parameters/ReverseGeocodingParameters.cs @@ -11,7 +11,7 @@ namespace Geo.Positionstack.Models.Parameters /// /// The parameters possible to use during a reverse geocoding request. /// - public class ReverseGeocodingParameters : ILocationGeocodeParameters, IFilterGeocodeParameters, IKeyParameters + public class ReverseGeocodingParameters : ILocationGeocodeParameters, IFilterGeocodeParameters, IKeyParameters, IAdditionalParameters { /// /// Gets or sets the coordinates to reverse geocode. @@ -47,5 +47,8 @@ public class ReverseGeocodingParameters : ILocationGeocodeParameters, IFilterGeo /// public string Key { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Positionstack/Services/PositionstackGeocoding.cs b/src/Geo.Positionstack/Services/PositionstackGeocoding.cs index ece407b..2718f6b 100644 --- a/src/Geo.Positionstack/Services/PositionstackGeocoding.cs +++ b/src/Geo.Positionstack/Services/PositionstackGeocoding.cs @@ -119,6 +119,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) AddFilterParameters(parameters, ref query); AddLocationParameters(parameters, ref query); AddPositionstackKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -147,6 +148,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) AddFilterParameters(parameters, ref query); AddLocationParameters(parameters, ref query); AddPositionstackKey(parameters, ref query); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/src/Geo.Radar/Models/Parameters/AutocompleteParameters.cs b/src/Geo.Radar/Models/Parameters/AutocompleteParameters.cs index a63abed..f06f9ef 100644 --- a/src/Geo.Radar/Models/Parameters/AutocompleteParameters.cs +++ b/src/Geo.Radar/Models/Parameters/AutocompleteParameters.cs @@ -10,7 +10,7 @@ namespace Geo.Radar.Models.Parameters /// /// The parameters possible to use during an autocomplete request. /// - public class AutocompleteParameters : ICountryParameter, ILayersParameter, IKeyParameters + public class AutocompleteParameters : ICountryParameter, ILayersParameter, IKeyParameters, IAdditionalParameters { /// /// Gets or sets the partial address or place name to autocomplete. @@ -40,5 +40,8 @@ public class AutocompleteParameters : ICountryParameter, ILayersParameter, IKeyP /// public string Key { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Radar/Models/Parameters/GeocodingParameters.cs b/src/Geo.Radar/Models/Parameters/GeocodingParameters.cs index c2acbb8..198bb78 100644 --- a/src/Geo.Radar/Models/Parameters/GeocodingParameters.cs +++ b/src/Geo.Radar/Models/Parameters/GeocodingParameters.cs @@ -11,7 +11,7 @@ namespace Geo.Radar.Models.Parameters /// /// The parameters possible to use during a geocoding request. /// - public class GeocodingParameters : ICountryParameter, ILayersParameter, IKeyParameters + public class GeocodingParameters : ICountryParameter, ILayersParameter, IKeyParameters, IAdditionalParameters { /// /// Gets or sets the address to geocode. @@ -26,5 +26,8 @@ public class GeocodingParameters : ICountryParameter, ILayersParameter, IKeyPara /// public string Key { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Radar/Models/Parameters/ReverseGeocodingParameters.cs b/src/Geo.Radar/Models/Parameters/ReverseGeocodingParameters.cs index 784a65c..cf8ff54 100644 --- a/src/Geo.Radar/Models/Parameters/ReverseGeocodingParameters.cs +++ b/src/Geo.Radar/Models/Parameters/ReverseGeocodingParameters.cs @@ -11,7 +11,7 @@ namespace Geo.Radar.Models.Parameters /// /// The parameters possible to use during a reverse geocoding request. /// - public class ReverseGeocodingParameters : ILayersParameter, IKeyParameters + public class ReverseGeocodingParameters : ILayersParameter, IKeyParameters, IAdditionalParameters { /// /// Gets or sets the coordinates to reverse geocode. @@ -23,5 +23,8 @@ public class ReverseGeocodingParameters : ILayersParameter, IKeyParameters /// public string Key { get; set; } + + /// + public IDictionary AdditionalParameters { get; } = new Dictionary(); } } diff --git a/src/Geo.Radar/Services/RadarGeocoding.cs b/src/Geo.Radar/Services/RadarGeocoding.cs index c840bed..4c08f05 100644 --- a/src/Geo.Radar/Services/RadarGeocoding.cs +++ b/src/Geo.Radar/Services/RadarGeocoding.cs @@ -131,6 +131,7 @@ internal Uri BuildGeocodingRequest(GeocodingParameters parameters) AddCountry(parameters, ref query); AddLayers(parameters, ref query); AddRadarKey(parameters); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -158,6 +159,7 @@ internal Uri BuildReverseGeocodingRequest(ReverseGeocodingParameters parameters) AddLayers(parameters, ref query); AddRadarKey(parameters); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); @@ -206,6 +208,7 @@ internal Uri BuildAutocompleteRequest(AutocompleteParameters parameters) AddCountry(parameters, ref query); AddLayers(parameters, ref query); AddRadarKey(parameters); + query = query.AddAdditionalParameters(parameters); uriBuilder.AddQuery(query); diff --git a/test/Geo.ArcGIS.Tests/Services/ArcGISGeocodingShould.cs b/test/Geo.ArcGIS.Tests/Services/ArcGISGeocodingShould.cs index 2c05353..3b99871 100644 --- a/test/Geo.ArcGIS.Tests/Services/ArcGISGeocodingShould.cs +++ b/test/Geo.ArcGIS.Tests/Services/ArcGISGeocodingShould.cs @@ -278,6 +278,25 @@ public void BuildAddressCandidateRequestWithException() #endif } + [Fact] + public async Task BuildAddressCandidateRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new AddressCandidateParameters() + { + SingleLineAddress = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = await sut.BuildAddressCandidateRequest(parameters, CancellationToken.None); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the place candidate uri is built properly. /// @@ -321,6 +340,22 @@ public async Task BuildPlaceCandidateRequestSuccessfully(CultureInfo culture) Thread.CurrentThread.CurrentCulture = oldCulture; } + [Fact] + public async Task BuildPlaceCandidateRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new PlaceCandidateParameters(); + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = await sut.BuildPlaceCandidateRequest(parameters, CancellationToken.None); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the findAddressCandidates uri is built properly using a single-line address. /// @@ -526,6 +561,25 @@ public void BuildSuggestRequestWithException() #endif } + [Fact] + public async Task BuildSuggestRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new SuggestParameters() + { + Text = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = await sut.BuildSuggestRequest(parameters, CancellationToken.None); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the reverse geocoding uri is built properly. /// @@ -594,6 +648,29 @@ public void BuildReverseGeocodingRequestWithException() #endif } + [Fact] + public async Task BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Location = new Coordinate() + { + Latitude = 80.012, + Longitude = 123.456, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = await sut.BuildReverseGeocodingRequest(parameters, CancellationToken.None); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the geocoding uri is built properly. /// @@ -675,6 +752,29 @@ public void BuildGeocodingRequestWithException() #endif } + [Fact] + public async Task BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters(); + + parameters.AddressAttributes.Add( + new AddressAttributeParameter() + { + ObjectId = 1, + SingleLine = "123 East", + }); + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = await sut.BuildGeocodingRequest(parameters, CancellationToken.None); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the geocoding uri includes outFields when the parameter is set. /// diff --git a/test/Geo.Bing.Tests/Services/BingGeocodingShould.cs b/test/Geo.Bing.Tests/Services/BingGeocodingShould.cs index b9a7a12..67b97c0 100644 --- a/test/Geo.Bing.Tests/Services/BingGeocodingShould.cs +++ b/test/Geo.Bing.Tests/Services/BingGeocodingShould.cs @@ -295,6 +295,25 @@ public void BuildGeocodingRequestSuccessfully(CultureInfo culture) Thread.CurrentThread.CurrentCulture = oldCulture; } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Query = "1 Microsoft Way Redmond WA", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the reverse geocoding uri isn't built if a point isn't passed in. /// @@ -361,6 +380,29 @@ public void BuildReverseGeocodingRequestSuccessfully(CultureInfo culture) Thread.CurrentThread.CurrentCulture = oldCulture; } + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Point = new Coordinate() + { + Latitude = 40.7567, + Longitude = -73.9897, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the address geocoding uri isn't built if not enought information is passed in. /// @@ -425,6 +467,25 @@ public void BuildAddressGeocodingRequestSuccessfully(CultureInfo culture) Thread.CurrentThread.CurrentCulture = oldCulture; } + [Fact] + public void BuildAddressGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new AddressGeocodingParameters() + { + AddressLine = "222 Bay Street", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildAddressGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the geocoding returns a response successfully. /// @@ -520,4 +581,4 @@ private BingGeocoding BuildService() return new BingGeocoding(_httpClient, _options.Object); } } -} \ No newline at end of file +} diff --git a/test/Geo.Core.Tests/Extensions/QueryStringExtensionsShould.cs b/test/Geo.Core.Tests/Extensions/QueryStringExtensionsShould.cs new file mode 100644 index 0000000..a3a2be8 --- /dev/null +++ b/test/Geo.Core.Tests/Extensions/QueryStringExtensionsShould.cs @@ -0,0 +1,151 @@ +// +// Copyright (c) Geo.NET. +// Licensed under the MIT license. See the LICENSE file in the solution root for full license information. +// + +namespace Geo.Core.Tests.Extensions +{ + using System.Collections.Generic; + using FluentAssertions; + using Geo.Core.Extensions; + using Xunit; + + /// + /// Unit tests for the class. + /// + public class QueryStringExtensionsShould + { + private class TestAdditionalParameters : IAdditionalParameters + { + public IDictionary AdditionalParameters { get; } = new Dictionary(); + } + + private class NullDictionaryAdditionalParameters : IAdditionalParameters + { +#pragma warning disable CS8603 // Possible null reference return. + public IDictionary AdditionalParameters => null; +#pragma warning restore CS8603 // Possible null reference return. + } + + /// + /// Tests that a null parameters object causes the original query to be returned unchanged. + /// + [Fact] + public void ReturnUnchangedQueryString_WhenParametersIsNull() + { + var query = QueryString.Empty.Add("existing", "value"); + + var result = query.AddAdditionalParameters(null); + + result.Should().Be(query); + } + + /// + /// Tests that a null AdditionalParameters dictionary causes the original query to be returned unchanged. + /// + [Fact] + public void ReturnUnchangedQueryString_WhenAdditionalParametersDictionaryIsNull() + { + var query = QueryString.Empty.Add("existing", "value"); + var parameters = new NullDictionaryAdditionalParameters(); + + var result = query.AddAdditionalParameters(parameters); + + result.Should().Be(query); + } + + /// + /// Tests that an empty AdditionalParameters dictionary causes the original query to be returned unchanged. + /// + [Fact] + public void ReturnUnchangedQueryString_WhenAdditionalParametersDictionaryIsEmpty() + { + var query = QueryString.Empty.Add("existing", "value"); + var parameters = new TestAdditionalParameters(); + + var result = query.AddAdditionalParameters(parameters); + + result.Should().Be(query); + } + + /// + /// Tests that a single additional key/value pair is appended to the query string. + /// + [Fact] + public void AddSingleKeyValuePair_ToQueryString() + { + var parameters = new TestAdditionalParameters(); + parameters.AdditionalParameters.Add("key1", "value1"); + + var result = QueryString.Empty.AddAdditionalParameters(parameters); + + result.Value.Should().Contain("key1=value1"); + } + + /// + /// Tests that multiple additional key/value pairs are all appended to the query string. + /// + [Fact] + public void AddMultipleKeyValuePairs_ToQueryString() + { + var parameters = new TestAdditionalParameters(); + parameters.AdditionalParameters.Add("key1", "value1"); + parameters.AdditionalParameters.Add("key2", "value2"); + parameters.AdditionalParameters.Add("key3", "value3"); + + var result = QueryString.Empty.AddAdditionalParameters(parameters); + + result.Value.Should().Contain("key1=value1"); + result.Value.Should().Contain("key2=value2"); + result.Value.Should().Contain("key3=value3"); + } + + /// + /// Tests that an entry with a null value is skipped and not appended to the query string. + /// + [Fact] + public void SkipEntry_WhenValueIsNull() + { + var parameters = new TestAdditionalParameters(); + parameters.AdditionalParameters.Add("nullkey", null); + + var result = QueryString.Empty.AddAdditionalParameters(parameters); + + result.Should().Be(QueryString.Empty); + } + + /// + /// Tests that only null-valued entries are skipped while non-null entries are added. + /// + [Fact] + public void SkipOnlyNullValueEntries_WhenMixedWithNonNullValues() + { + var parameters = new TestAdditionalParameters(); + parameters.AdditionalParameters.Add("key1", "value1"); + parameters.AdditionalParameters.Add("nullkey", null); + parameters.AdditionalParameters.Add("key3", "value3"); + + var result = QueryString.Empty.AddAdditionalParameters(parameters); + + result.Value.Should().Contain("key1=value1"); + result.Value.Should().NotContain("nullkey"); + result.Value.Should().Contain("key3=value3"); + } + + /// + /// Tests that additional parameters are appended after existing query parameters. + /// + [Fact] + public void AppendAdditionalParameters_AfterExistingQueryParameters() + { + var query = QueryString.Empty.Add("existing", "value"); + var parameters = new TestAdditionalParameters(); + parameters.AdditionalParameters.Add("extra", "data"); + + var result = query.AddAdditionalParameters(parameters); + + result.Value.Should().Contain("existing=value"); + result.Value.Should().Contain("extra=data"); + } + } +} diff --git a/test/Geo.Google.Tests/Services/GoogleGeocodingShould.cs b/test/Geo.Google.Tests/Services/GoogleGeocodingShould.cs index 48e9da4..13521cc 100644 --- a/test/Geo.Google.Tests/Services/GoogleGeocodingShould.cs +++ b/test/Geo.Google.Tests/Services/GoogleGeocodingShould.cs @@ -1047,6 +1047,29 @@ protected virtual void Dispose(bool disposing) _disposed = true; } + /// + /// Tests the additional parameters are properly included in the geocoding request uri. + /// + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_IncludesThemInUri() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Address = "123 East", + }; + + parameters.AdditionalParameters.Add("custom_param", "custom_value"); + parameters.AdditionalParameters.Add("version", "2"); + + var uri = sut.BuildGeocodingRequest(parameters); + + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("custom_param=custom_value"); + query.Should().Contain("version=2"); + } + private GoogleGeocoding BuildService() { return new GoogleGeocoding(_httpClient, _options.Object); diff --git a/test/Geo.Here.Tests/Services/HereGeocodingShould.cs b/test/Geo.Here.Tests/Services/HereGeocodingShould.cs index f14131b..a97ee3f 100644 --- a/test/Geo.Here.Tests/Services/HereGeocodingShould.cs +++ b/test/Geo.Here.Tests/Services/HereGeocodingShould.cs @@ -714,6 +714,25 @@ public void BuildGeocodingRequestFailsWithException() #endif } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodeParameters() + { + Query = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the reverse geocoding parameters is done successfully. /// @@ -814,6 +833,29 @@ public void BuildReverseGeocodingRequestFailsWithException() /// /// Tests the building of the reverse geocoding parameters fails if no query is provided. /// + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodeParameters() + { + At = new Coordinate() + { + Latitude = 56.78, + Longitude = 78.91, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Fact] public void BuildReverseGeocodingRequest_WithBothInAndAt_FailsWithException() { @@ -910,6 +952,30 @@ public void BuildDiscoverRequestFailsWithException() #endif } + [Fact] + public void BuildDiscoverRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new DiscoverParameters() + { + Query = "123 East", + At = new Coordinate() + { + Latitude = 54.2, + Longitude = 45.2, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildDiscoverRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the autosuggest parameters is done successfully. /// @@ -975,6 +1041,30 @@ public void BuildAutosuggestRequestFailsWithException() #endif } + [Fact] + public void BuildAutosuggestRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new AutosuggestParameters() + { + Query = "123 East", + At = new Coordinate() + { + Latitude = 54.2, + Longitude = 45.2, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildAutosuggestRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the browse parameters is done successfully. /// @@ -1038,6 +1128,29 @@ public void BuildBrowseRequestFailsWithException() #endif } + [Fact] + public void BuildBrowseRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new BrowseParameters() + { + At = new Coordinate() + { + Latitude = 54.2, + Longitude = 45.2, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildBrowseRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the lookup parameters is done successfully. /// @@ -1089,6 +1202,25 @@ public void BuildLookupRequestFailsWithException() #endif } + [Fact] + public void BuildLookupRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new LookupParameters() + { + Id = "12345sudfinm", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildLookupRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the validation and creation of the lookup uri is done successfully. /// diff --git a/test/Geo.MapBox.Tests/Services/MapBoxGeocodingShould.cs b/test/Geo.MapBox.Tests/Services/MapBoxGeocodingShould.cs index ae63b25..fa41427 100644 --- a/test/Geo.MapBox.Tests/Services/MapBoxGeocodingShould.cs +++ b/test/Geo.MapBox.Tests/Services/MapBoxGeocodingShould.cs @@ -280,6 +280,25 @@ public void BuildGeocodingRequestFailsWithException() #endif } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Query = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the reverse geocoding parameters is done successfully. /// @@ -357,6 +376,29 @@ public void BuildReverseGeocodingRequestFailsWithException() #endif } + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Coordinate = new Coordinate() + { + Latitude = 56.78, + Longitude = 78.91, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the validation and creation of the reverse geocoding uri is done successfully. /// @@ -561,4 +603,4 @@ private MapBoxGeocoding BuildService() return new MapBoxGeocoding(_httpClient, _options.Object); } } -} \ No newline at end of file +} diff --git a/test/Geo.MapQuest.Tests/Services/MapQuestGeocodingShould.cs b/test/Geo.MapQuest.Tests/Services/MapQuestGeocodingShould.cs index 05db971..04e20c2 100644 --- a/test/Geo.MapQuest.Tests/Services/MapQuestGeocodingShould.cs +++ b/test/Geo.MapQuest.Tests/Services/MapQuestGeocodingShould.cs @@ -288,6 +288,25 @@ public void BuildGeocodingRequestFailsWithException() #endif } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Location = "1 Microsoft Way Redmond WA", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the building of the licensed reverse geocoding parameters is done successfully. /// @@ -401,6 +420,29 @@ public void BuildReverseGeocodingRequestFailsWithException() #endif } + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Location = new Coordinate() + { + Latitude = 56.78, + Longitude = 78.91, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + /// /// Tests the validation and creation of the reverse geocoding uri is done successfully. /// @@ -566,4 +608,4 @@ private MapQuestGeocoding BuildService() return new MapQuestGeocoding(_httpClient, _options.Object); } } -} \ No newline at end of file +} diff --git a/test/Geo.Positionstack.Tests/Services/PositionstackGeocodingShould.cs b/test/Geo.Positionstack.Tests/Services/PositionstackGeocodingShould.cs index 87c8f00..4ffe847 100644 --- a/test/Geo.Positionstack.Tests/Services/PositionstackGeocodingShould.cs +++ b/test/Geo.Positionstack.Tests/Services/PositionstackGeocodingShould.cs @@ -222,6 +222,25 @@ public void BuildGeocodingRequest_WithInvalidParameters_FailsWithException() #endif } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Query = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Theory] [ClassData(typeof(CultureTestData))] public void BuildReverseGeocodingRequest_WithValidParameters_SuccessfullyBuildsUrl(CultureInfo culture) @@ -269,6 +288,29 @@ public void BuildReverseGeocodingRequest_WithInvalidParameters_FailsWithExceptio #endif } + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Coordinate = new Coordinate() + { + Latitude = 56.78, + Longitude = 78.91, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Fact] public void ValidateAndBuildUri_WithValidParameters_SuccessfullyBuildsUri() { @@ -345,4 +387,4 @@ private PositionstackGeocoding BuildService() return new PositionstackGeocoding(_httpClient, _options.Object); } } -} \ No newline at end of file +} diff --git a/test/Geo.Radar.Tests/Services/RadarGeocodingShould.cs b/test/Geo.Radar.Tests/Services/RadarGeocodingShould.cs index a288754..136c932 100644 --- a/test/Geo.Radar.Tests/Services/RadarGeocodingShould.cs +++ b/test/Geo.Radar.Tests/Services/RadarGeocodingShould.cs @@ -216,6 +216,25 @@ public void BuildGeocodingRequest_WithCharacterNeedingEncoding_SuccessfullyBuild uri.PathAndQuery.Should().Contain("query=123%20East%20%23425"); } + [Fact] + public void BuildGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new GeocodingParameters() + { + Query = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Fact] public void BuildGeocodingRequest_WithInvalidParameters_FailsWithException() { @@ -284,6 +303,29 @@ public void BuildReverseGeocodingRequest_WithInvalidParameters_FailsWithExceptio #endif } + [Fact] + public void BuildReverseGeocodingRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new ReverseGeocodingParameters() + { + Coordinate = new Coordinate() + { + Latitude = 56.78, + Longitude = 78.91, + }, + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildReverseGeocodingRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Theory] [ClassData(typeof(CultureTestData))] public void BuildAutocompleteRequest_WithValidParameters_SuccessfullyBuildsUrl(CultureInfo culture) @@ -345,6 +387,25 @@ public void BuildAutocompleteRequest_WithInvalidParameters_FailsWithException() #endif } + [Fact] + public void BuildAutocompleteRequest_WithAdditionalParameters_AddsThemToQueryString() + { + var sut = BuildService(); + + var parameters = new AutocompleteParameters() + { + Query = "123 East", + }; + + parameters.AdditionalParameters.Add("customKey1", "customValue1"); + parameters.AdditionalParameters.Add("customKey2", "customValue2"); + + var uri = sut.BuildAutocompleteRequest(parameters); + var query = HttpUtility.UrlDecode(uri.PathAndQuery); + query.Should().Contain("customKey1=customValue1"); + query.Should().Contain("customKey2=customValue2"); + } + [Fact] public void ValidateAndBuildUri_WithValidParameters_SuccessfullyBuildsUri() { @@ -477,4 +538,4 @@ private RadarGeocoding BuildService() return new RadarGeocoding(_httpClient, _options.Object); } } -} \ No newline at end of file +}