0

My application makes calls out to a bunch of different external API classes. To facilitate this, I have a class for each external API to be called, all of which inherit from a base class which starts like this:

public abstract class ApiBase : 
{
    protected static HttpClient client = new HttpClient();
    protected EntityFrameWorkCredentialObject credential;

    public bool AccountSupported(int accountId)
    {
        using (var context = DBProvider.GetTransientEntityContext())
        {
            credential = context.EntityFrameWorkCredentialObject
                            .Where(x => x.AccountId == accountId.FirstOrDefault();
        }

        return credential != null;
    }
}

These objects are created via a factory class, through which it is impossible to get an instance of an object without first checking AccountSupported. So any instance of a class which inherits this base will have its credential populated.

Most of these APIs are either public or accept a key as part of the request. However, we now have to deal with a new API which requires a network credential. The documentation for HttpClient says this has to be passed into the object when it's created.

using (var handler = new HttpClientHandler { Credentials = ... })
using (var client = new HttpClient(handler))
{
    var result = await client.GetAsync(...);
}

That's obviously going to cause problems for the way my object is built, since it creates an HttpClient when it's instantiated, and relies on getting the credentials after the fact.

Is there no way to set the credentials on an existing object, or another way out of this without doing a ton of refactoring?

Bob Tway
  • 9,301
  • 17
  • 80
  • 162
  • 1
    I would try something like this. https://stackoverflow.com/questions/10077237/httpclient-authentication-header-not-getting-sent – Ryan Schlueter Nov 28 '18 at 15:49
  • 1
    You could try managing the handler upfront along with a [CredentialCache Class](https://learn.microsoft.com/en-us/dotnet/api/system.net.credentialcache?view=netframework-4.7.2). based on the request endpoint you decide if to enable `UseDefaultCredentials` – Nkosi Nov 28 '18 at 15:49
  • 1
    @RyanSchlueter Sweet, that did the job, thanks – Bob Tway Nov 28 '18 at 15:58

1 Answers1

3

All that the credentials thing does is to add the required authentication header to the httpclient requests.

You can always go ahead and add authentication headers manually by setting default request headers:

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer","Token");
client.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Basic",
    Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "yourusername", "yourpwd"))));
Tim Cadenbach
  • 1,446
  • 1
  • 9
  • 21