HttpClient example (C#)

Dave Gray 586 Reputation points
2021-10-27T15:15:10.61+00:00

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

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,018 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 54,816 Reputation points
    2021-10-27T16:57:38+00:00

    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
    }
    
    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Dave Gray 586 Reputation points
    2021-10-28T10:12:20.617+00:00

    Hi @Michael Taylor

    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

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.