Search code examples
c#httpclient

How can I add a query string into HttpClient.BaseAdress in c#?


I'm trying to pass a query string into a BaseAddress but it doesn't recognize the quotation mark "?".

The quotation breaks the URI

First I create my BaseAddress

httpClient.BaseAddress = new Uri($"https://api.openweathermap.org/data/2.5/weather?appid={Key}/"); 

Then I call the GetAsync method, trying to add another parameter

using (var response = await ApiHelper.httpClient.GetAsync("&q=mexico"))....

This is the URI the code is calling

https://api.openweathermap.org/data/2.5/&q=mexico

Solution

  • I'd be tempted to use a DelegatingHandler if you need to apply an API key to every single request:

    private class KeyHandler : DelegatingHandler
    {
        private readonly string _escapedKey;
    
        public KeyHandler(string key)  : this(new HttpClientHandler(), key)
        {
        }
    
        public KeyHandler(HttpMessageHandler innerHandler, string key) : base(innerHandler)
        {
            // escape the key since it might contain invalid characters
            _escapedKey = Uri.EscapeDataString(key);
        }
    
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // we'll use the UriBuilder to parse and modify the url
            var uriBuilder = new UriBuilder(request.RequestUri);
    
            // when the query string is empty, we simply want to set the appid query parameter
            if (string.IsNullOrEmpty(uriBuilder.Query))
            {
                uriBuilder.Query = $"appid={_escapedKey}";
            }
            // otherwise we want to append it
            else
            {
                uriBuilder.Query = $"{uriBuilder.Query}&appid={_escapedKey}";
            }
            // replace the uri in the request object
            request.RequestUri = uriBuilder.Uri;
            // make the request as normal
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    Usage:

    httpClient = new HttpClient(new KeyHandler(Key));
    httpClient.BaseAddress = new Uri($"https://api.openweathermap.org/data/2.5/weather"); 
    
    // since the logic of adding/appending the appid is done based on what's in
    // the query string, you can simply write `?q=mexico` here, instead of `&q=mexico`
    using (var response = await ApiHelper.httpClient.GetAsync("?q=mexico"))
    

    ** Note: If you're using ASP.NET Core, you should call services.AddHttpClient() and then use IHttpHandlerFactory to generate the inner handler for KeyHandler.