saurabh dhyani
saurabh dhyani

Reputation: 93

How to reuse HttpClient reference for multiple http requests

I have a code where I am creating an instance of HttpClient, which is inside of a foreach loop. Which means it is creating a new instance for each time the iteration takes place. Here is my code :

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Text;
using System.Net.Mime;
using System.Net.Http.Json;

public class Program
   {
        static async Task Main(string[] args)
        {
            //JSON String
            string json = @"{
            'Values': [
                {
                    'MsgSource': null,
                    'TagName': 'Data.New_MSG',
                    'RawValue': '[\r\n  {\r\n    \'ID\': 145,\r\n    \'StationNo\': 6,\r\n    
                                 \'RunTime\': 1800,\r\n    \'ControllerID\': 4,\r\n    
                                 \'ControllerAddress\': 2,\r\n    \'ProgramNo\': 2,\r\n    
                                 \'ModeID\': \'AutoProgram\',\r\n    \'EventDate\': \'2022-04- 
                                 27T23:30:02\',\r\n    \'Description\': \'Irrigation 
                                 Completed\',\r\n    \'MessageCode\': 5\r\n,\r\n    
                                 \'ControllerName\': \'P25-SC-0233\'  },\r\n  {\r\n    \'ID\': 
                                 144,\r\n    \'StationNo\': 18,\r\n    \'RunTime\': 1800,\r\n    
                                 \'ControllerID\': 4,\r\n    \'ControllerAddress\': 2,\r\n    
                                 \'ProgramNo\': 5,\r\n    \'ModeID\': \'AutoProgram\',\r\n    
                                 \'EventDate\': \'2022-04-27T22:00:00\',\r\n    \'Description\': 
                                 \'Irrigation Completed\',\r\n    \'MessageCode\': 5\r\n,\r\n    
                                 \'ControllerName\': \'P25-SC-0226\'  }\r\n]',
                    'Status': 'Normal',
                    'ComStatus': null,
                    'TimeStamp': '2022-04-28 13:17:39.851'
                }
                ]
            }";

            //Deserializing JSON String
            Root root = JsonConvert.DeserializeObject<Root>(json);
            //Extracting the value of only RawValue key from the String
            string rawValue = root.Values[0].RawValue;

            //Creating List of ControllerName key            
            List<Station> stations = JsonConvert.DeserializeObject<List<Station>>(rawValue);
            
            JArray array = JArray.Parse(rawValue);
            
            int i = 0;    //Initializing Index to add ControllerName to the URL in Get http 
                          //request below
            foreach(var item in array) //Iterating through array
            {
                
                  var inc_val = i++;
                
                  using (var client = new HttpClient()) //Here I've Instantiated HttpClient
                  {
                    
                    client.DefaultRequestHeaders.Authorization = new 
                    AuthenticationHeaderValue("Basic","auth_value"); //Basic Auth

                    //Mandatory key for Message body in Post request
                    string isoTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
                    
                    //Concatenating ControllerName in URL and making get request
                    HttpResponseMessage get_response = await 
                    client.GetAsync("https://myurl.com/"+stations[inc_val]);

                    var get_responseString = await get_response.Content.ReadAsStringAsync();

                    JObject obj = JObject.Parse(get_responseString);

                    //Extracting id from the response of Get request which has to be used in
                    //Post Data when making Post request
                    string name = (string) obj["managedObject"]["id"];

                    //Required JSON Body structure which needs to be merged with Post Data
                    string json2 =    $"{{\"time\": \"{isoTime}\",\"source\": {{\"id\": \"{name}\" 
                    }},\"type\": \"c8y_Golf_Controller\",\"text\": \"PilotCC Data New Msg\"}}";

                    JObject json3 = JObject.Parse(json2);
                    var result = new JObject();
                    result.Merge(item);
                    result.Merge(json3);
                    string json4 = JsonConvert.SerializeObject(result);
                    
                    client.DefaultRequestHeaders.Add("Accept", 
                    "application/vnd.com.nsn.cumulocity.event+json"); //More Headers
                    
                    var stringContent = new StringContent(json4, Encoding.UTF8, 
                    "application/json");
                    
                    stringContent.Headers.ContentType.CharSet = "";

                    //Making Post request                    
                    HttpResponseMessage response = await client.PostAsync("https://myurl.com", 
                    stringContent);

                    var responseString = await response.Content.ReadAsStringAsync();

                    Console.WriteLine(responseString);
                }
          }

     }
        
      public class Root
      {
          public List<Value> Values {get; set;}
      }
      public class Value
      {
          public string RawValue { get; set; }
      }

      public class Station
      {
            [JsonProperty("ControllerName")]
            public string ControllerName { get; set; }

            public override string ToString()
            {
               return String.Format(ControllerName);
            }
      }        
}

How do I make it better by not creating unnecessary instances of HttpClient each time foreach loop iteration in triggered and instead reuse the single instance of HttpClient for making all the http requests??

Upvotes: 2

Views: 2034

Answers (1)

Fildor
Fildor

Reputation: 16104

In your case, it would be enough to ...

public class Program
{
    static async Task Main()
    {
         // Create one single instance outside the loop ...
         var client = new HttpClient();

         // more code here

         foreach( var item in array ) 
         {
             // ... then use it.
             var response = await client.GetAsync(/* yadda yadda */);
         }
    }
}

Upvotes: 3

Related Questions