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