2

i'm trying to make a app thats lets me query the database from discogs.

According to the Api documentation i can do this with just a token. so i registered and got a user token.

now when i use postman with https://api.discogs.com/database/search?release_title=nevermind&artist=nirvana&per_page=3&page=1&token=<my_user_token> i receive the json like i would expect.

but when i make a httpclient in c# with the token

    public string token = <my_user_token>;
    public static HttpClient client { get; set; }
    public static async Task InitilizeClient()
    {
        await GetAccesToken();
    }

    private static async Task GetAccesToken()
    {
        client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Clear();
        client.BaseAddress = new Uri(@"https://api.discogs.com");
        //client.DefaultRequestHeaders.Authorization=new AuthenticationHeaderValue("Discogs", "token="+token);
        client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization","Discogs token=" + token);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

and then use the client like this

    public static async Task QueryDataBaseAsync(string query)
    {
       if (query == null)
        {
            throw new Exception("query is empty");
        }
        string url = "";
        url = @"https://api.discogs.com/database/search?release_title="+query;
        if (client == null)
        {
            await InitilizeClient();
        }
        using (HttpResponseMessage response = await client.GetAsync(url))
        {
            if (response.IsSuccessStatusCode)
            {

            }
            else
            {
                throw new Exception(response.ReasonPhrase + " \n" + response.RequestMessage.ToString());
            }
        }

    }

then i always get a ReasonPhrase "forbidden","statuscode: 403"

when i put a breakpoint on my HttpResponseMessage response i can see that under "headers"=>"responsemessage"=>"headers"=>"authorization" it has my token.

what am i doing wrong?

ps, sorry about the bad english, its not my motherlangue

ps2, i'm new at programming so i would appreciate it if you could eli5 what i did wrong

Community
  • 1
  • 1
Sageza
  • 23
  • 4
  • Where is `token` defined and initialized? Also, in the working PostMan request, it's not a header but a query string parameter. – CodeCaster Oct 14 '19 at 13:37
  • public string token is initialized in my constructor before calling InitilizeClient(); i will edit the original question to reflect that – Sageza Oct 14 '19 at 13:37
  • The best way of debugging is to use a sniffer like fiddler or wireshark and verify you headers are correct. The Net Http class uses different default headers. The content type which is not specified by vendor is the browser compatibility. The server may be expecting Chrome Compatibility and you are sending IE type. The API may be expecting SSL and you are using wrong version of SSL encryption. I would start by taking vendor software that works and compare to your c# headers to verify the differences. – jdweng Oct 14 '19 at 13:47
  • I have an answer that is close to what you are trying to do. Maybe it can help with the sequence of events. https://stackoverflow.com/questions/38494279/how-do-i-get-an-oauth-2-0-authentication-token-in-c-sharp/53787718#53787718 – granadaCoder Oct 14 '19 at 13:55

1 Answers1

2

You may need to provide user-agent in the headers. Something along these lines:

client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36");

like this:

public class DiscConsumer
{
    //https://www.discogs.com/developers#page:authentication,header:authentication-discogs-auth-flow
    //curl "https://api.discogs.com/database/search?q=Nirvana" -H "Authorization: Discogs key=foo123, secret=bar456"

    private const string _urlQuery = "https://api.discogs.com/database/search?q={query}";
    private const string _key = "<....your key....>";
    private const string _secret = "<....your secret...>";

    private System.Net.Http.HttpClient _httpClient;
    public async Task InitilizeClient()
    {
        //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
        var sslhandler = new HttpClientHandler()
        {
            //...in System.Security.Authentication.SslProtocols
            SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
        };
        _httpClient = new System.Net.Http.HttpClient(sslhandler);
        string authorization = $"Discogs key={_key}, secret={_secret}";
        _httpClient.DefaultRequestHeaders.Add("Authorization", authorization);
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36");
    }

    public async Task QueryDataBaseAsync(string query)
    {
        if (String.IsNullOrWhiteSpace( query ))
        {
            throw new Exception("query is empty");
        }
        string url = "";
        url = _urlQuery.Replace("{query}", query);
        if (_httpClient == null)
        {
            await InitilizeClient();
        }
        using (HttpResponseMessage response = await _httpClient.GetAsync(url))
        {
            if (response.IsSuccessStatusCode)
            {
                string s = await response.Content.ReadAsStringAsync();
                Console.WriteLine(s);
            }
            else
            {
                throw new Exception(response.ReasonPhrase + " \n" + response.RequestMessage.ToString());
            }
        }
    }
}

Per https://www.discogs.com/developers#page:authentication,header:authentication-discogs-auth-flow you can supply key+secret on every request along with search.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
yob
  • 528
  • 4
  • 9