1
votes

I know this question might seem like a duplicate, but I have tried every solution I saw before asking this question again.

I'm trying to consume a REST API which I wrote myself with Django Rest Framework, using C# HttpClient in Xamarin Forms. The request is being sent but it does not include the required Authorization with Token as scheme.

Here are the things I've tried:

public async Task<IssueListModelView> FetchIssues(string token, string type)
{
    client.BaseAddress = new Uri(XTMonitorContants.SERVICE_BASE_URL);
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(XTMonitorContants.SERVICE_ISSUES_URL + type.ToLower()));

    request.Headers.Add("Authorization", "Token " + token);

    //client.
    //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); 
    client.DefaultRequestHeaders.Add("Authorization", "Token " + token);
    var response = client.SendAsync(request);
    var jsonString = response.ContinueWith(t => { return t.Result; }).Result.Content.ReadAsStringAsync().Result;

    IssueListModelView resp = new IssueListModelView();
    if (jsonString != "")
    {
        try
        {
            resp = JsonConvert.DeserializeObject<IssueListModelView>(jsonString);
        }
        catch (Exception)
        {
            resp.error = "Internal Server Error";
        }

    }
    return resp;
}

I have also tried to send the request directly without using HttpRequestMessage, but also gave me the same server response of

"Authentication credentials were not provided."

Request made by Postman

GET /api/issues/all HTTP/1.1

Host: example.com

Authorization: Token ffba1c43ac346945b788768e2a428d5e5d3c1fc9

Cache-Control: no-cache

Postman-Token: 0c1eb96d-d9d6-a9e7-0cfa-0444fdc0248e

Request made by HttpClient

{Method: GET, RequestUri: 'https://example.com/api/issues/all', Version: 1.1, Content: <null>, Headers: { Authorization: Token ffba1c43ac346945b788768e2a428d5e5d3c1fc9 }}

Please note that I've tested the API properly using Postman and also setup Swagger, it works fine on both.

Would be glad if someone could give me a hand here, as I think there's probably something I'm missing out

2
Try using a plain HttpWebRequest, HttpClient has many bugs. - Gusman
@Gusman thanks, I'd check it out as I've not used it before now. - phourxx

2 Answers

0
votes

Try not to mix blocking (.Result) and async code. Make the method async all the way.

Also when setting the request Authorization header try using the Authorization property on the headers

request.Headers.Authorization = new AuthenticationHeaderValue(tokenType, token);

Refactored method

public async Task<IssueListModelView> FetchIssues(string token, string type) {
    client.BaseAddress = new Uri(XTMonitorContants.SERVICE_BASE_URL);
    var uri = new Uri(XTMonitorContants.SERVICE_ISSUES_URL + type.ToLower());
    var request = new HttpRequestMessage(HttpMethod.Get, uri);
    request.Headers.Authorization = new AuthenticationHeaderValue("Token", token);

    var response = await client.SendAsync(request);
    var jsonString = await response.Content.ReadAsStringAsync();

    IssueListModelView resp = new IssueListModelView();
    if (jsonString != "") {
        try {
            resp = JsonConvert.DeserializeObject<IssueListModelView>(jsonString);
        } catch (Exception) {
            resp.error = "Internal Server Error";
        }
    }
    return resp;
}
0
votes

Okay, after thorough checks, I found out that I was missing a trailing slash in my url, the server was redirecting my request from example.com/api/issues/all to example.com/api/issues/all/ so it wasn't maintaining the header while redirecting.

Finally, for other people that might run into same problem, or could be trying to consume API, you might want to checkout Flurl, I was able to make the whole request thing and deserialize the json directly to C# object with a single line, cool right?

Thanks for your responses @Nkosi