How can I do named resolve for c# azure function

Henry Zhang 206 Reputation points
2024-01-23T21:16:02.6433333+00:00

Hi, My .net 8 c# azure function behaves like a request forwarder, it will forward incoming HTTP requests to different backend endpoints.

So I have a service class:
public class ProxyServices(ILogger<ProxyServices> logger, HttpClient httpClient, IOptions<AppSettings> options)
If I inject a HttpClient with base url pointing to endpoint A, then this service will forward request to A.

So my DI for HttpClient is looking like this:

        services.AddHttpClient("guestApiClient",client =>
        {
            client.BaseAddress = new Uri(appSettings.ApiGuestsBaseUrl);
        }).AddHttpMessageHandler<BearerTokenHandler>();

        services.AddKeyedTransient<IProxyService, ProxyServices>("endpontA", (serviceProvider, _)=>
        {
            resolving logger and options.....
            var httpClient = httpClientFactory.CreateClient("MyNamedClient");

            return new ProxyServices(logger, httpClient, options);
        });


I will have KeyedTransient for "endpointB" ,C , D ......

Now my question is in my c# function class, how can I do a named resolve for proxyServices, for some function I want endpointA version of ProxyServices, other functions might want endpointB, C version.

Or how can I configure the DI so it knows for FunctionA, it should resolved "endpointA" version of proxyServices

public class AddToWaitlist(IProxyServices proxyServices, IOptions<AppSettings> options, IValidationServices validationServices)
{
    private readonly AppSettings _appSettings = options.Value;

    [Function("AddToWaitlist")]
    public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "viewings/waitlist")] HttpRequestData req)

Thanks, Henry

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,911 questions
{count} votes

2 answers

Sort by: Most helpful
  1. JananiRamesh-MSFT 29,261 Reputation points
    2024-01-29T18:44:06.3133333+00:00

    @Henry Zhang Thanks for reaching out. Could you please use the concept of named or keyed registrations in Dependency Injection (DI) setup. In  Startup class, configure the named registrations for different endpoints. For each endpoint, add a named HttpClient and a corresponding transient service.

    public class Startup : FunctionsStartup  
    {  
        public override void Configure(IFunctionsHostBuilder builder)  
        {  
            var appSettings = /* retrieve or inject your AppSettings here */;
     
            builder.Services.AddHttpClient("endpointA", client =>  
            {  
                client.BaseAddress = new Uri(appSettings.ApiEndpointA);  
            }).AddHttpMessageHandler<BearerTokenHandler>();
     
            builder.Services.AddTransient<IProxyService, ProxyServices>("endpointA");  
            // ... Add more registrations for other endpoints  
        }  
    } 
    
    1. In function class, use the Inject attribute to specify which named registration of IProxyService you want for that function.
    public class AddToWaitlist  
    {  
        private readonly IProxyService _proxyService;
     
        public AddToWaitlist([Inject("endpointA")] IProxyService proxyService)  
        {  
            _proxyService = proxyService;  
        }
     
        [Function("AddToWaitlist")]  
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "viewings/waitlist")] HttpRequestData req)  
        {  
            // Use _proxyService here  
            // ...  
        }  
    }  
    

    By using the [Inject] attribute with the specified key (“endpointA” in this example), you’re telling the Azure Functions runtime to resolve the IProxyService using the named registration you configured in the Startup class.  This way, you can have different versions of ProxyServices for different functions, each pointing to a different endpoint.

    Please try and let me know if this helps!


  2. Saravanan Ganesan 1,830 Reputation points MVP
    2024-01-29T19:30:57.5666667+00:00

    Hi Henry , To achieve named resolution for IProxyServices in your Azure Function, you can use the [Inject] attribute in the function method parameters. Modify your function as follows:

    public class AddToWaitlist
    {
        private readonly IProxyServices _proxyServices;
    
        public AddToWaitlist([Inject("endpointA")] IProxyServices proxyServices)
        {
            _proxyServices = proxyServices;
        }
    
        [Function("AddToWaitlist")]
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "viewings/waitlist")] HttpRequestData req)
        {
            // Your function logic using _proxyServices
        }
    }
    
    
    

    This way, you specify the named resolution directly in the function's constructor using the [Inject] attribute. Repeat the pattern for other functions with different endpoints. Regards, Saravanan Ganesan .


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.