diff --git a/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs b/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs
index 293e28bf..76861994 100644
--- a/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs
+++ b/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs
@@ -62,6 +62,7 @@ namespace Example.CLI.PersistentConfig
var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers());
Console.WriteLine($"Total Playlists in your Account: {playlists.Count}");
+ _server.Dispose();
Environment.Exit(0);
}
diff --git a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
index 92816b2f..df1fd4b5 100644
--- a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
+++ b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
@@ -4,6 +4,20 @@ namespace SpotifyAPI.Web
{
public interface IOAuthClient
{
+ ///
+ /// Requests a new token using client_ids and client_secrets.
+ /// If the token is expired, simply call the funtion again to get a new token
+ ///
+ ///
+ ///
Task RequestToken(ClientCredentialsRequest request);
+
+ ///
+ /// Refresh an already received token via Authorization Code Auth
+ ///
+ ///
+ ///
+ Task RequestToken(AuthorizationCodeRefreshRequest request);
+ Task RequestToken(AuthorizationCodeTokenRequest request);
}
}
diff --git a/SpotifyAPI.Web/Models/Request/RequestParams.cs b/SpotifyAPI.Web/Models/Request/RequestParams.cs
index 2762e4e9..6859c2ac 100644
--- a/SpotifyAPI.Web/Models/Request/RequestParams.cs
+++ b/SpotifyAPI.Web/Models/Request/RequestParams.cs
@@ -1,3 +1,4 @@
+using System.Collections.Concurrent;
using System.Reflection;
using System;
using System.Linq;
@@ -9,69 +10,73 @@ namespace SpotifyAPI.Web
{
public abstract class RequestParams
{
+ private static readonly ConcurrentDictionary _bodyParamsCache =
+ new ConcurrentDictionary();
public JObject BuildBodyParams()
{
// Make sure everything is okay before building body params
CustomEnsure();
- var bodyProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
- .Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
-
- var obj = new JObject();
- foreach (var prop in bodyProps)
+ var body = new JObject();
+ if (!_bodyParamsCache.IsEmpty)
{
- object value = prop.GetValue(this);
- if (value != null && prop.GetCustomAttribute(typeof(BodyParamAttribute)) is BodyParamAttribute attribute)
+ foreach (var bodyParam in _bodyParamsCache)
{
- obj[attribute.Key ?? prop.Name] = JToken.FromObject(value);
+ AddBodyParam(body, bodyParam.Key, bodyParam.Value);
}
}
- return obj;
+ else
+ {
+ var bodyProps = GetType()
+ .GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
+ .Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
+
+ foreach (var prop in bodyProps)
+ {
+ var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
+ _bodyParamsCache[prop] = attribute;
+ AddBodyParam(body, prop, attribute);
+ }
+ }
+
+ return body;
}
+ private void AddBodyParam(JObject body, PropertyInfo prop, BodyParamAttribute attribute)
+ {
+ object value = prop.GetValue(this);
+ if (value != null)
+ {
+ body[attribute.Key ?? prop.Name] = JToken.FromObject(value);
+ }
+ }
+
+ private static readonly ConcurrentDictionary _queryParamsCache =
+ new ConcurrentDictionary();
public Dictionary BuildQueryParams()
{
// Make sure everything is okay before building query params
CustomEnsure();
- var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
+ var queryParams = new Dictionary();
+
+ if (!_queryParamsCache.IsEmpty)
+ {
+ foreach (var queryParam in _queryParamsCache)
+ {
+ AddQueryParam(queryParams, queryParam.Key, queryParam.Value);
+ }
+ }
+ else
+ {
+ var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0);
- var queryParams = new Dictionary();
- foreach (var prop in queryProps)
- {
- object value = prop.GetValue(this);
- if (value != null && prop.GetCustomAttribute(typeof(QueryParamAttribute)) is QueryParamAttribute attribute)
+ foreach (var prop in queryProps)
{
- if (value is IList list && list.Count > 0)
- {
- var str = string.Join(",", list);
- queryParams.Add(attribute.Key ?? prop.Name, str);
- }
- else if (value is Enum valueAsEnum)
- {
- var enumType = valueAsEnum.GetType();
- var valueList = new List();
-
- foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType()))
- {
- if (valueAsEnum.HasFlag(enumVal))
- {
- if (enumType
- .GetMember(enumVal.ToString())[0]
- .GetCustomAttributes(typeof(StringAttribute))
- .FirstOrDefault() is StringAttribute stringAttr)
- {
- valueList.Add(stringAttr.Value);
- }
- }
- }
- queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList));
- }
- else
- {
- queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
- }
+ var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
+ _queryParamsCache[prop] = attribute;
+ AddQueryParam(queryParams, prop, attribute);
}
}
@@ -80,6 +85,43 @@ namespace SpotifyAPI.Web
return queryParams;
}
+ private void AddQueryParam(Dictionary queryParams, PropertyInfo prop, QueryParamAttribute attribute)
+ {
+ object value = prop.GetValue(this);
+ if (value != null)
+ {
+ if (value is IList list && list.Count > 0)
+ {
+ var str = string.Join(",", list);
+ queryParams.Add(attribute.Key ?? prop.Name, str);
+ }
+ else if (value is Enum valueAsEnum)
+ {
+ var enumType = valueAsEnum.GetType();
+ var valueList = new List();
+
+ foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType()))
+ {
+ if (valueAsEnum.HasFlag(enumVal))
+ {
+ if (enumType
+ .GetMember(enumVal.ToString())[0]
+ .GetCustomAttributes(typeof(StringAttribute))
+ .FirstOrDefault() is StringAttribute stringAttr)
+ {
+ valueList.Add(stringAttr.Value);
+ }
+ }
+ }
+ queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList));
+ }
+ else
+ {
+ queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
+ }
+ }
+ }
+
protected virtual void CustomEnsure() { }
protected virtual void AddCustomQueryParams(Dictionary queryParams) { }
}