question

DaveGray-0128 avatar image
0 Votes"
DaveGray-0128 asked DaveGray-0128 answered

HttpClient example (C#)

Hello

Just getting started with consuming APIs so please bare with. :-(

I have my API setup in Postman and all works fine, I need to transfer this to a Console application (for now), however I am getting 404 not found.
Having waded thru a load of really old examples online for the HttpClient class, I found one that looked simple enough to get going with, however I must have
got the authentication wrong in my C#

The string "api-key" was from the original example buy I feel this must be wrong, not sure what to put in here though...

I have attached the C# code and the screens from Postman that I have changed values.

Any help would be great,

Thanks
144203-vs.png


144168-postmanroot.png


144254-postman-authorization.png


144272-postmanheaders.png



dotnet-csharp
vs.png (179.0 KiB)
postmanroot.png (37.3 KiB)
postmanheaders.png (77.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

cooldadtx avatar image
1 Vote"
cooldadtx answered

Couple of things.

  1. At least for .NET Framework you don't want to create HttpClient over and over again otherwise you'll run out of ports. Google for the issues around doing that. So you should create the client once and reuse it per URL.

  2. When creating the HttpClient set the default request headers and BaseAddress to what you're using in Postman as the base URL. Then use relative URLs in the individual get/post requests.

  3. API-Key would be an authentication mechanism and depends upon the API you're calling. If your API doesn't need authentication then you don't need this. If it does then you'd already be doing that in Postman and you'd need to replicate it.

My preferred approach is to use an HttpClientFactory to handle creation of clients by name and it handles the creation for you. NET Core ships with a version but for NF you have to build your own.

For authentication I tend to create an HttpMessageHandler class that injects the API key into all requests sent by that client. But that is a slightly more advanced scenario.

For your very specific starter case something like this should work for .NET Core (and similar for .NET Framework).

class Program
{
    static async Task Main ( string[] args )
    {
        var users = await PagerDutyClient.ListUsersAsync().ConfigureAwait(false);
        foreach (var user in users)
        {
        };
    }

    private static PagerDutyClient CreateClient ()
    {
        //The uri MUST contain an ending slash otherwise HttpClient does not work correctly
        var client = new HttpClient() {
            BaseAddress = new Uri("https://api.pagerduty/"),
            DefaultRequestHeaders = {
                { "api-key", "mykey" }
            }
        };

        return new PagerDutyClient(client);
    }

    private static PagerDutyClient PagerDutyClient => _client.Value;

    private static readonly Lazy<PagerDutyClient> _client = new Lazy<PagerDutyClient>(CreateClient);
}

public class PagerDutyClient
{
    public PagerDutyClient ( HttpClient client )
    {
        _client = client;
    }

    public async Task<IEnumerable<User>> ListUsersAsync ( CancellationToken cancellationToken = default )
    {
        //Could also use a generic GetAsync<T> implementation if you have one
        using (var response = await _client.GetAsync("users", cancellationToken).ConfigureAwait(false))
        {
            response.EnsureSuccessStatusCode();

            //Using default System.Net.Json, could also use JSON.NET via JsonConvert.
            return await JsonSerializer.DeserializeAsync<IEnumerable<User>>(response.Content.ReadAsStream()
                                            , cancellationToken: cancellationToken).ConfigureAwait(false);
        };
    }

    private readonly HttpClient _client;
}

public class User
{
    //Put your data here
}




5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DaveGray-0128 avatar image
0 Votes"
DaveGray-0128 answered

Hi @cooldadtx

Thanks for your detailed and comprehensive answer, it looks to be a big help. :-)

I did get my sandbox test working by changing "api-key" to "Authorization", which matches the screen in Postman that
I forgot to include in my original post

144498-image.png




It's going to take me a few days to test out and understand the factory methods so I will mark this one as answered and post a
fresh question later (if necessary).

Thanks again


image.png (49.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.