Skip to content

Commit 66064aa

Browse files
committed
Added migration from 5.x to 6.x to docs
1 parent 35dbc7f commit 66064aa

File tree

3 files changed

+168
-9
lines changed

3 files changed

+168
-9
lines changed

SpotifyAPI.Docs/docs/5_to_6.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
---
2+
id: 5_to_6
3+
title: 5.x.x to 6.x.x
4+
---
5+
6+
## SpotifyAPI.Web
7+
8+
### Initialization
9+
10+
In `5.x`, a new `SpotifyWebAPI` instance could be created without supplying necessary values, since they were implemented as properties. With `6.x`, necessary values have to be given in the constructor and `SpotifyWebAPI` has been renamed to `SpotifyClient`. Also, `SpotifyClientConfig` has been introduced to give a better configuration experience, including retry handlers, automatic authenticators and proxy configurations.
11+
12+
```csharp
13+
// OLD
14+
var spotify = new SpotifyWebAPI { AccessToken = "YourAccessToken" };
15+
var spotify = new SpotifyWebAPI(ProxyConfig); // No access token - invalid
16+
17+
// NEW
18+
var spotify = new SpotifyClient("YourAccessToken");
19+
20+
var config = SpotifyClientConfig
21+
.CreateDefault()
22+
.WithToken("YourAccessToken");
23+
var spotify = new SpotifyClient(config);
24+
25+
var config = SpotifyClientConfig
26+
.CreateDefault()
27+
.WithAuthenticator(new ClientCredentialsAuthenticator(CLIENT_ID, CLIENT_SECRET)); // takes care of access tokens
28+
var spotify = new SpotifyClient(config);
29+
```
30+
31+
For some performance guides, have a look at the [Configuration Guide](./configuration.md)
32+
33+
### Proxy
34+
35+
In `5.x`, the proxy configuration could be passed to the `SpotifyWebAPI` constructor. In `6.x`, they're part of the HTTP Client. The built-in http client supports proxies out of the box:
36+
37+
```csharp
38+
var httpClient = new NetHttpClient(new ProxyConfig("localhost", 8080)
39+
{
40+
User = "",
41+
Password = "",
42+
SkipSSLCheck = false,
43+
});
44+
var config = SpotifyClientConfig
45+
.CreateDefault()
46+
.WithHTTPClient(httpClient);
47+
48+
var spotify = new SpotifyClient(config);
49+
```
50+
51+
### Calling API Endpoints
52+
53+
In `5.x`, there was one big instance to support all API endpoints. Parameters to these endpoints were passed directly as method parameters. Optional parameters were nullable and could be excluded. In `6.x`, every endpoint group (`albums`, `tracks`, `userprofile`) has their own API-Client, which is available as a property in a `SpotifyClient` instance. While URI path parameters are still passed as method parameter, query and body parameters are now passed as a grouped class instance, where required parameters are needed in the constructor and optional parameters can be supplied as properties. All endpoints are also only implemented as async methods.
54+
55+
```csharp
56+
// OLD:
57+
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
58+
var playlists = await spotify.GetUserPlaylists(profile.Id, 100, 0);
59+
60+
// NEW:
61+
PrivateUser user = await spotify.UserProfile.Current();
62+
var playlists = await spotify.Playlists.GetUsers(user.Id, new PlaylistGetUsersRequest
63+
{
64+
Limit = 100,
65+
Offset = 0
66+
});
67+
```
68+
69+
All required arguments are checked for non-null values. If it's null, the methods will throw a `ArgumentNullException`
70+
71+
### Error/Header Handling
72+
73+
In `5.x`, all response models included a base error model, with properties like `Headers`, `Error` and `HasError`. This was not a good decision since response models should be clean and only contain API response data. In `6.x`, error handling is `Exception` based. For example, if the access token is invalid, calling API endpoints will throw a `APIUnauthorizedException`. If you hit the API too many times, the method will throw a `APITooManyRequestsException`. They all derive from a base exception `APIException`, which is also thrown in more general cases, e.g bad request input parameters. If you're interested in the headers of the last response, you can use `spotify.LastResponse`, **make sure there is only one thread using this instance!**
74+
75+
```csharp
76+
// OLD:
77+
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
78+
if(profile.HasError())
79+
{
80+
// handle error
81+
}
82+
var headers = profile.Headers(); // access to headers
83+
84+
// NEW:
85+
try
86+
{
87+
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
88+
var response = spotify.LastResponse; // response.Headers
89+
}
90+
catch (APIUnauthorizedException e)
91+
{
92+
// handle unauthorized error
93+
// e.Response contains HTTP response
94+
// e.Message contains Spotify error message
95+
}
96+
catch (APIException e)
97+
{
98+
// handle common error
99+
// e.Response contains HTTP response
100+
// e.Message contains Spotify error message
101+
}
102+
```
103+
104+
More Info: [Error Handling](./error_handling)
105+
106+
## SpotifyAPI.Web.Auth
107+
108+
In `5.x`, `SpotifyAPI.Web.Auth` contained every logic related to the OAuth flows. In `6.x`, `SpotifyAPI.Web.Auth` is only required if you need a HTTP Server for handling OAuth responses. For example, if you're in a ASP.NET environment or just use the [Client Credentials](client_credentials) flow, there is no need to install `SpotifyAPI.Web.Auth` anymore.
109+
110+
### Authorization Code Auth
111+
112+
As an example, this shows how to convert a `5.x` authorization code flow to `6.x`:
113+
114+
```csharp
115+
// OLD
116+
var auth =
117+
new AuthorizationCodeAuth(_clientId, _secretId, "http://localhost:4002", "http://localhost:4002",
118+
Scope.PlaylistReadPrivate | Scope.PlaylistReadCollaborative);
119+
auth.AuthReceived += AuthOnAuthReceived;
120+
auth.Start();
121+
auth.OpenBrowser();
122+
123+
private static async void AuthOnAuthReceived(object sender, AuthorizationCode payload)
124+
{
125+
var auth = (AuthorizationCodeAuth) sender;
126+
auth.Stop();
127+
128+
Token token = await auth.ExchangeCode(payload.Code);
129+
var spotify = new SpotifyWebAPI { AccessToken = token.AccessToken };
130+
await PrintUsefulData(spotify);
131+
}
132+
133+
// NEW
134+
var config = SpotifyClientConfig.CreateDefault();
135+
var server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
136+
server.AuthorizationCodeReceived += async (sender, response) =>
137+
{
138+
await server.Stop();
139+
var tokenResponse = await new OAuthClient(config).RequestToken(new AuthorizationCodeTokenRequest(
140+
_clientId, _secretId, response.Code, server.BaseUri
141+
));
142+
143+
var spotify = new SpotifyClient(config.WithToken(tokenResponse.AccessToken));
144+
}
145+
await server.Start();
146+
147+
var loginRequest = new LoginRequest(server.BaseUri, _clientId, LoginRequest.ResponseType.Code)
148+
{
149+
Scope = new[] { Scopes.PlaylistReadPrivate, Scopes.PlaylistReadCollaborative }
150+
};
151+
BrowserUtil.Open(loginRequest.ToUri());
152+
```
153+
154+
While it is more code to write, there is a better seperation of concerns. For example, it is able to construct a `LoginRequest` without starting a server. This `LoginRequest` can also be used to forward the user to in a web-based context. The same auth server `EmbedIOAuthServer` can be used to receive `AuthorizationCodes` and `ImplictGrants` responses.

SpotifyAPI.Docs/sidebars.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ module.exports = {
1414
'pagination',
1515
'retry_handling',
1616
'iplayableitem',
17-
'unit_testing'
18-
]
17+
'unit_testing',
18+
],
1919
},
2020
{
2121
type: 'category',
@@ -26,8 +26,8 @@ module.exports = {
2626
'implicit_grant',
2727
'authorization_code',
2828
'pkce',
29-
'token_swap'
30-
]
29+
'token_swap',
30+
],
3131
},
3232
'showcase',
3333
{
@@ -40,9 +40,14 @@ module.exports = {
4040
'example_cli_custom_html',
4141
'example_cli_persistent_config',
4242
'example_token_swap',
43-
'example_uwp'
44-
]
43+
'example_uwp',
44+
],
4545
},
46-
]
47-
}
46+
{
47+
type: 'category',
48+
label: 'Migration Guides',
49+
items: ['5_to_6'],
50+
},
51+
],
52+
},
4853
};

SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Example.CLI.PersistentConfig.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
<TargetFramework>net5.0</TargetFramework>
66
<LangVersion>8.0</LangVersion>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>

0 commit comments

Comments
 (0)