mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-25 07:26:28 +00:00
155 lines
6.2 KiB
Markdown
155 lines
6.2 KiB
Markdown
---
|
|
id: 5_to_6
|
|
title: 5.x.x to 6.x.x
|
|
---
|
|
|
|
## SpotifyAPI.Web
|
|
|
|
### Initialization
|
|
|
|
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.
|
|
|
|
```csharp
|
|
// OLD
|
|
var spotify = new SpotifyWebAPI { AccessToken = "YourAccessToken" };
|
|
var spotify = new SpotifyWebAPI(ProxyConfig); // No access token - invalid
|
|
|
|
// NEW
|
|
var spotify = new SpotifyClient("YourAccessToken");
|
|
|
|
var config = SpotifyClientConfig
|
|
.CreateDefault()
|
|
.WithToken("YourAccessToken");
|
|
var spotify = new SpotifyClient(config);
|
|
|
|
var config = SpotifyClientConfig
|
|
.CreateDefault()
|
|
.WithAuthenticator(new ClientCredentialsAuthenticator(CLIENT_ID, CLIENT_SECRET)); // takes care of access tokens
|
|
var spotify = new SpotifyClient(config);
|
|
```
|
|
|
|
For some performance guides, have a look at the [Configuration Guide](./configuration.md)
|
|
|
|
### Proxy
|
|
|
|
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:
|
|
|
|
```csharp
|
|
var httpClient = new NetHttpClient(new ProxyConfig("localhost", 8080)
|
|
{
|
|
User = "",
|
|
Password = "",
|
|
SkipSSLCheck = false,
|
|
});
|
|
var config = SpotifyClientConfig
|
|
.CreateDefault()
|
|
.WithHTTPClient(httpClient);
|
|
|
|
var spotify = new SpotifyClient(config);
|
|
```
|
|
|
|
### Calling API Endpoints
|
|
|
|
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.
|
|
|
|
```csharp
|
|
// OLD:
|
|
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
|
|
var playlists = await spotify.GetUserPlaylists(profile.Id, 100, 0);
|
|
|
|
// NEW:
|
|
PrivateUser user = await spotify.UserProfile.Current();
|
|
var playlists = await spotify.Playlists.GetUsers(user.Id, new PlaylistGetUsersRequest
|
|
{
|
|
Limit = 100,
|
|
Offset = 0
|
|
});
|
|
```
|
|
|
|
All required arguments are checked for non-null values. If it's null, the methods will throw a `ArgumentNullException`
|
|
|
|
### Error/Header Handling
|
|
|
|
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!**
|
|
|
|
```csharp
|
|
// OLD:
|
|
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
|
|
if(profile.HasError())
|
|
{
|
|
// handle error
|
|
}
|
|
var headers = profile.Headers(); // access to headers
|
|
|
|
// NEW:
|
|
try
|
|
{
|
|
PrivateProfile profile = await spotify.GetPrivateProfileAsync();
|
|
var response = spotify.LastResponse; // response.Headers
|
|
}
|
|
catch (APIUnauthorizedException e)
|
|
{
|
|
// handle unauthorized error
|
|
// e.Response contains HTTP response
|
|
// e.Message contains Spotify error message
|
|
}
|
|
catch (APIException e)
|
|
{
|
|
// handle common error
|
|
// e.Response contains HTTP response
|
|
// e.Message contains Spotify error message
|
|
}
|
|
```
|
|
|
|
More Info: [Error Handling](./error_handling)
|
|
|
|
## SpotifyAPI.Web.Auth
|
|
|
|
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.
|
|
|
|
### Authorization Code Auth
|
|
|
|
As an example, this shows how to convert a `5.x` authorization code flow to `6.x`:
|
|
|
|
```csharp
|
|
// OLD
|
|
var auth =
|
|
new AuthorizationCodeAuth(_clientId, _secretId, "http://localhost:4002", "http://localhost:4002",
|
|
Scope.PlaylistReadPrivate | Scope.PlaylistReadCollaborative);
|
|
auth.AuthReceived += AuthOnAuthReceived;
|
|
auth.Start();
|
|
auth.OpenBrowser();
|
|
|
|
private static async void AuthOnAuthReceived(object sender, AuthorizationCode payload)
|
|
{
|
|
var auth = (AuthorizationCodeAuth) sender;
|
|
auth.Stop();
|
|
|
|
Token token = await auth.ExchangeCode(payload.Code);
|
|
var spotify = new SpotifyWebAPI { AccessToken = token.AccessToken };
|
|
await PrintUsefulData(spotify);
|
|
}
|
|
|
|
// NEW
|
|
var config = SpotifyClientConfig.CreateDefault();
|
|
var server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
|
|
server.AuthorizationCodeReceived += async (sender, response) =>
|
|
{
|
|
await server.Stop();
|
|
var tokenResponse = await new OAuthClient(config).RequestToken(new AuthorizationCodeTokenRequest(
|
|
_clientId, _secretId, response.Code, server.BaseUri
|
|
));
|
|
|
|
var spotify = new SpotifyClient(config.WithToken(tokenResponse.AccessToken));
|
|
}
|
|
await server.Start();
|
|
|
|
var loginRequest = new LoginRequest(server.BaseUri, _clientId, LoginRequest.ResponseType.Code)
|
|
{
|
|
Scope = new[] { Scopes.PlaylistReadPrivate, Scopes.PlaylistReadCollaborative }
|
|
};
|
|
BrowserUtil.Open(loginRequest.ToUri());
|
|
```
|
|
|
|
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.
|