Spotify.NET/SpotifyAPI.Docs/docs/5_to_6.md
2023-05-27 21:43:01 +02:00

6.2 KiB

id title
5_to_6 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.

// 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

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:

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.

// 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!

// 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

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 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:

// 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:5543/callback"), 5543);
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.