3

Scenario:

I need to load work items from two project management systems (VSTS and Jira) through their REST API. Each of them has different authorization mechanism:

  • VSTS: Using access token that load from database, varied by team/group of users
  • Jira: Using personal token that load from user claims, varied by user

Basic classes and an interface:

public interface IProjectManagementClient
{
    ProjectManagementType Type { get; }
    Task<WorkItem> GetWorkItemAsync(ProjectManagement projectManagement, int id, CancellationToken token = default(CancellationToken));
    Task<List<WorkItem>> GetAllWorkItemsAsync(ProjectManagement projectManagement, string term, int limit = 10, CancellationToken token = default(CancellationToken));
}

public enum ProjectManagementType
{
    VSTS,
    Jira
}

public class ProjectManagement
{
    public int Id { get; set; }
    public ProjectManagementType Type { get; set; }
    public string BaseAddress { get; set; }
    public string AccessToken { get; set; }
}

Setup:

services.AddHttpClient<IProjectManagementClient, VstsClient>();
services.AddHttpClient<IProjectManagementClient, JiraClient>()
    .AddHttpMessageHandler(provider => new BasicAuthHandler(provider.GetService<IHttpContextAccessor>(), CustomClaimTypes.TrackerToken));

Usage example:

public TimesheetsController(IEnumerable<IProjectManagementClient> projectManagementClients)
{
    _projectManagementClients = projectManagementClients;
}

public void DoWork()
{
    foreach (var timesheet in _timesheets)
    {
        var projectManagementClient = _projectManagementClients.First(o => o.Type == timesheet.ProjectManagement.Type);
        timesheet.WorkItem = timesheet.WorkItemId.HasValue
            ? await projectManagementClient.GetWorkItemAsync(timesheet.ProjectManagement, timesheet.WorkItemId.Value, token)
            : null;
    }
}

Issues:

Even though I've only registered the BasicAuthHandler to the JiraClient. It has been applied to both VSTS and Jira clients.

Thus it has overridden the VSTS authorization that has been set previously in VstsClient.

Both works fine if I only setup and use only of them at a time. Please help.

1
  • Show your realization of IProjectManagementClient i.e. VstsClient and JiraClient. Commented Oct 15, 2018 at 10:03

1 Answer 1

3

JiraClient gets overriden by VstsClient because they are both registered on the same (null) name, which is default. Try to use named registrations:

services.AddHttpClient<IProjectManagementClient, VstsClient>("VSTS");
services.AddHttpClient<IProjectManagementClient, JiraClient>("JIRA")
    .AddHttpMessageHandler(provider => new BasicAuthHandler(
        provider.GetService<IHttpContextAccessor>(),
        CustomClaimTypes.TrackerToken));

In this case IEnumerable<IProjectManagementClient> should give two items, configured as above, without override.

Sign up to request clarification or add additional context in comments.

5 Comments

You aren't required to specify name for typed clients. It depends on client realization: stevejgordon.co.uk/…
@xneg yes, this is another option. However, in order to inject both clients as IEnumerable<IProjectManagementClient> one needs names.
Yes, thank you. Adding the name solves my problem. But I don't think JiraClient is overridden by VstsClient, they are both injected fine into the example controller.
@stop-cran: they are NOT registered on the same null name. I kind of explained here: stackoverflow.com/a/77492045/2410655. The name is the short name of the interface. In this case, it's IProjectManagementClient, which happens to be the same. Hence the HttpClient instance on both typed clients is the same instance!
@stop-cran: also, to be technically correct, JiraClient doesn't get overriden by VstsClient. They both exist in the DI. You can see them by doing services.GetServices<IProjectManagementClient>(). You will get 2 back.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.