Skip to content

Commit 208b90f

Browse files
committed
Fixed cache logic inside of RequestParams, fixes #458
1 parent 3e0c4e4 commit 208b90f

File tree

2 files changed

+77
-12
lines changed

2 files changed

+77
-12
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Newtonsoft.Json;
4+
using NUnit.Framework;
5+
6+
namespace SpotifyAPI.Web.Tests
7+
{
8+
[TestFixture]
9+
public class RequestParamsTest
10+
{
11+
[Test]
12+
public void CacheDoesNotInterfereQuery()
13+
{
14+
var first = new FirstRequestModel { First = true };
15+
var firstParams = first.BuildQueryParams();
16+
17+
var second = new SecondRequestModel { Second = false };
18+
var secondParams = second.BuildQueryParams();
19+
20+
Assert.AreEqual(1, firstParams.Keys.Count);
21+
Assert.AreEqual("true", firstParams["first"]);
22+
23+
Assert.AreEqual(1, secondParams.Keys.Count);
24+
Assert.AreEqual("false", secondParams["second"]);
25+
}
26+
27+
[Test]
28+
public void CacheDoesNotInterfereBody()
29+
{
30+
var first = new FirstRequestModel { First = true };
31+
var firstParams = first.BuildBodyParams();
32+
33+
var second = new SecondRequestModel { Second = false };
34+
var secondParams = second.BuildBodyParams();
35+
36+
Assert.AreEqual("{\"first\":true}", firstParams.ToString(Formatting.None));
37+
Assert.AreEqual("{\"second\":false}", secondParams.ToString(Formatting.None));
38+
}
39+
}
40+
41+
public class FirstRequestModel : RequestParams
42+
{
43+
[BodyParam("first")]
44+
[QueryParam("first")]
45+
public bool? First { get; set; }
46+
}
47+
48+
public class SecondRequestModel : RequestParams
49+
{
50+
[BodyParam("second")]
51+
[QueryParam("second")]
52+
public bool? Second { get; set; }
53+
}
54+
}

SpotifyAPI.Web/Models/Request/RequestParams.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ namespace SpotifyAPI.Web
1010
{
1111
public abstract class RequestParams
1212
{
13-
private static readonly ConcurrentDictionary<PropertyInfo, BodyParamAttribute> _bodyParamsCache =
14-
new ConcurrentDictionary<PropertyInfo, BodyParamAttribute>();
13+
private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>> _bodyParamsCache =
14+
new ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>>();
15+
1516
public JObject BuildBodyParams()
1617
{
1718
// Make sure everything is okay before building body params
1819
CustomEnsure();
1920

2021
var body = new JObject();
21-
if (!_bodyParamsCache.IsEmpty)
22+
var type = GetType();
23+
24+
if (!_bodyParamsCache.IsEmpty && _bodyParamsCache.ContainsKey(type))
2225
{
23-
foreach (var bodyParam in _bodyParamsCache)
26+
foreach (var (info, attribute) in _bodyParamsCache[type])
2427
{
25-
AddBodyParam(body, bodyParam.Key, bodyParam.Value);
28+
AddBodyParam(body, info, attribute);
2629
}
2730
}
2831
else
@@ -31,10 +34,11 @@ public JObject BuildBodyParams()
3134
.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
3235
.Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
3336

37+
_bodyParamsCache[type] = new List<(PropertyInfo, BodyParamAttribute)>();
3438
foreach (var prop in bodyProps)
3539
{
3640
var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
37-
_bodyParamsCache[prop] = attribute;
41+
_bodyParamsCache[type].Add((prop, attribute));
3842
AddBodyParam(body, prop, attribute);
3943
}
4044
}
@@ -51,31 +55,34 @@ private void AddBodyParam(JObject body, PropertyInfo prop, BodyParamAttribute at
5155
}
5256
}
5357

54-
private static readonly ConcurrentDictionary<PropertyInfo, QueryParamAttribute> _queryParamsCache =
55-
new ConcurrentDictionary<PropertyInfo, QueryParamAttribute>();
58+
private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>> _queryParamsCache =
59+
new ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>>();
60+
5661
public Dictionary<string, string> BuildQueryParams()
5762
{
5863
// Make sure everything is okay before building query params
5964
CustomEnsure();
6065

6166
var queryParams = new Dictionary<string, string>();
67+
var type = GetType();
6268

63-
if (!_queryParamsCache.IsEmpty)
69+
if (!_queryParamsCache.IsEmpty && _queryParamsCache.ContainsKey(type))
6470
{
65-
foreach (var queryParam in _queryParamsCache)
71+
foreach (var (info, attribute) in _queryParamsCache[type])
6672
{
67-
AddQueryParam(queryParams, queryParam.Key, queryParam.Value);
73+
AddQueryParam(queryParams, info, attribute);
6874
}
6975
}
7076
else
7177
{
7278
var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
7379
.Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0);
7480

81+
_queryParamsCache[type] = new List<(PropertyInfo, QueryParamAttribute)>();
7582
foreach (var prop in queryProps)
7683
{
7784
var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
78-
_queryParamsCache[prop] = attribute;
85+
_queryParamsCache[type].Add((prop, attribute));
7986
AddQueryParam(queryParams, prop, attribute);
8087
}
8188
}
@@ -95,6 +102,10 @@ private void AddQueryParam(Dictionary<string, string> queryParams, PropertyInfo
95102
var str = string.Join(",", list);
96103
queryParams.Add(attribute.Key ?? prop.Name, str);
97104
}
105+
else if (value is bool valueAsBool)
106+
{
107+
queryParams.Add(attribute.Key ?? prop.Name, valueAsBool ? "true" : "false");
108+
}
98109
else if (value is Enum valueAsEnum)
99110
{
100111
var enumType = valueAsEnum.GetType();

0 commit comments

Comments
 (0)