Skip to content

Commit baa6a91

Browse files
authored
Merge pull request #8 from DavitRekhviashvili/master
QueryParamCollection upgrade by QueryStringBuilder
2 parents c15d269 + 9704905 commit baa6a91

File tree

5 files changed

+159
-18
lines changed

5 files changed

+159
-18
lines changed
Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,32 @@
11
using System.Collections.Specialized;
22
using System.Net;
3+
using System.Linq;
4+
using System.Web;
5+
using System.Text;
6+
using TBC.OpenAPI.SDK.Core.QueryStringHelper;
37

48
namespace TBC.OpenAPI.SDK.Core.Models
59
{
610
public sealed class QueryParamCollection : Dictionary<string, ParamValue>
7-
{
11+
{
812
public string ToQueryString()
913
{
10-
var query = new NameValueCollection();
11-
14+
var queryStringBulder = QueryStringBuilder.StartBuild();
1215
foreach (var item in this)
1316
{
14-
var value = item.Value;
15-
if (value?.Value is not null)
17+
if (item.Value?.Value is not null)
1618
{
17-
query.Add(item.Key, value.ToString());
19+
queryStringBulder.AddParameter(item.Key, item.Value.Value);
1820
}
19-
else
20-
if (value?.Values is not null)
21+
else if (item.Value?.Values is not null)
2122
{
22-
foreach (var v in value.Values)
23+
foreach (var v in item.Value.Values)
2324
{
24-
query.Add(item.Key, v.ToString());
25+
queryStringBulder.AddParameter(item.Key, v.ToString());
2526
}
2627
}
2728
}
28-
29-
if (!query.HasKeys())
30-
return string.Empty;
31-
32-
var segments = query.AllKeys.SelectMany(key => query.GetValues(key),
33-
(key, value) => $"{WebUtility.UrlEncode(key)}={WebUtility.UrlEncode(value)}");
34-
35-
return "?" + string.Join("&", segments);
29+
return queryStringBulder.Finish().GetBuildedQuery();
3630
}
3731
}
3832
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
6+
{
7+
internal interface IAddParameterable
8+
{
9+
10+
IAddParameterable AddParameter(string name, string value);
11+
IFinisher Finish();
12+
13+
}
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
6+
{
7+
internal interface IFinisher
8+
{
9+
string GetBuildedQuery();
10+
}
11+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using System.Text.Encodings.Web;
5+
6+
namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
7+
{
8+
internal class QueryStringBuilder:IAddParameterable, IFinisher
9+
{
10+
protected StringBuilder sb = new StringBuilder();
11+
private QueryStringBuilder(string startingString)
12+
{
13+
sb.Append(startingString);
14+
}
15+
public static IAddParameterable StartBuild(string rootaddress = null)
16+
{
17+
return new QueryStringBuilder(rootaddress == null?"?":$"{rootaddress}?");
18+
}
19+
public IAddParameterable AddParameter(string name, string value)
20+
{
21+
if (!string.IsNullOrWhiteSpace(value) && !string.IsNullOrWhiteSpace(name))
22+
{
23+
sb.Append($"{UrlEncoder.Default.Encode(name)}={UrlEncoder.Default.Encode(value)}&");
24+
}
25+
26+
return this;
27+
}
28+
public IFinisher Finish()
29+
{
30+
if(sb[sb.Length - 1] == '&' || sb[sb.Length - 1] == '?')
31+
{
32+
sb.Remove(sb.Length - 1, 1);
33+
}
34+
return this;
35+
}
36+
public string GetBuildedQuery()
37+
{
38+
return sb.ToString();
39+
}
40+
}
41+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using TBC.OpenAPI.SDK.Core.Models;
7+
using Xunit;
8+
using FluentAssertions;
9+
using System.Net;
10+
using System.Web;
11+
using System.Text.Encodings.Web;
12+
13+
namespace TBC.OpenAPI.SDK.Core.Tests
14+
{
15+
public class ComponentTests
16+
{
17+
[Theory]
18+
[InlineData("name", "Shota Rustaveli")]
19+
[InlineData("name", "Shota&Rustaveli")]
20+
[InlineData("name", "Shota?Rustaveli")]
21+
[InlineData("name?", "ShotaRustaveli")]
22+
[InlineData("name&", "ShotaRustaveli")]
23+
[InlineData("name!", "ShotaRustaveli")]
24+
[InlineData("(name)", "ShotaRustaveli")]
25+
[InlineData("name", "Shota! Rustaveli")]
26+
[InlineData("name", "Shota.Rustaveli")]
27+
[InlineData("name", "Shota_Rustaveli")]
28+
[InlineData("name", "Shota-Rustaveli")]
29+
[InlineData("name", "Shota(Rustaveli)")]
30+
[InlineData("name", "შოთა რუსთაველი")]
31+
public void QueryParamCollection_ToQueryString_UrlEncode_RespondShouldBePositive(string key, string value)
32+
{
33+
//Arrange
34+
QueryParamCollection col = new QueryParamCollection();
35+
col.Add("paramKey", "paramValue");
36+
col.Add(key, value);
37+
38+
//act
39+
var result = col.ToQueryString();
40+
41+
//assert
42+
result.Should().NotBeNullOrEmpty();
43+
var shouldBe = $"?paramKey=paramValue&{UrlEncoder.Default.Encode(key)}={UrlEncoder.Default.Encode(value)}";
44+
result.Should().Be(shouldBe);
45+
}
46+
47+
[Theory]
48+
[InlineData("", "Shota Rustaveli")]
49+
[InlineData("Name", null)]
50+
[InlineData("Name", "")]
51+
[InlineData("", "")]
52+
public void QueryParamCollection_ToQueryString_IfHaveNullKeyOrValue_PositiveCases(string key, string value)
53+
{
54+
//Arrange
55+
QueryParamCollection col = new QueryParamCollection();
56+
col.Add(key, value);
57+
58+
//act
59+
var result = col.ToQueryString();
60+
61+
//assert
62+
var shouldBe = "";
63+
result.Should().Be(shouldBe);
64+
}
65+
66+
[Theory]
67+
[InlineData(null, "Shota Rustaveli")]
68+
[InlineData(null, null)]
69+
public void QueryParamCollection_ToQueryString_IfHaveNullKeyOrValue_ThrowException(string key, string value)
70+
{
71+
//Arrange
72+
QueryParamCollection col = new QueryParamCollection();
73+
74+
//act
75+
Action result = ()=> col.Add(key, value);
76+
77+
//assert
78+
result.Should().Throw<ArgumentNullException>();
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)