Decompressing GZip Stream from HTTPClient Response Decompressing GZip Stream from HTTPClient Response json json

Decompressing GZip Stream from HTTPClient Response


Just instantiate HttpClient like this:

HttpClientHandler handler = new HttpClientHandler(){    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate};using (var client = new HttpClient(handler)) //see update below{    // your code}

Update June 19, 2020:It's not recommended to use httpclient in a 'using' block as it might cause port exhaustion.

private static HttpClient client = null;    ContructorMethod(){   if(client == null)   {        HttpClientHandler handler = new HttpClientHandler()        {            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate        };                client = new HttpClient(handler);   }// your code             }

If using .Net Core 2.1+, consider using IHttpClientFactory and injecting like this in your startup code.

 var timeout = Policy.TimeoutAsync<HttpResponseMessage>(            TimeSpan.FromSeconds(60)); services.AddHttpClient<XApiClient>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler        {            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate        }).AddPolicyHandler(request => timeout);


I used code from below link to decompress GZip stream.Then used the decompressed byte array to get the required JSON object. Hope it may help some one.

var readTask = result.Content.ReadAsByteArrayAsync().Result;var decompressedData = Decompress(readTask);string jsonString = System.Text.Encoding.UTF8.GetString(decompressedData, 0, decompressedData.Length);ResponseObjectClass responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseObjectClass>(jsonString);

https://www.dotnetperls.com/decompress

static byte[] Decompress(byte[] gzip){    using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))    {        const int size = 4096;        byte[] buffer = new byte[size];        using (MemoryStream memory = new MemoryStream())        {            int count = 0;            do            {                count = stream.Read(buffer, 0, size);                if (count > 0)                {                    memory.Write(buffer, 0, count);                }            }            while (count > 0);            return memory.ToArray();        }    }}


Ok so I eventually solved my problem. If there are better ways please let me know :-)

        public DataSet getData(string strFoo)    {        string url = "foo";        HttpClient client = new HttpClient();        HttpResponseMessage response;           DataSet dsTable = new DataSet();        try        {               //Gets the headers that should be sent with each request            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));              //Returned JSON            response = client.GetAsync(url).Result;              //converts JSON to string            string responseJSONContent = response.Content.ReadAsStringAsync().Result;              //deserializes string to list            var jsonList = DeSerializeJsonString(responseJSONContent);              //converts list to dataset. Bad name I know.            dsTable = Foo_ConnectAPI.ExtentsionHelpers.ToDataSet<RootObject>(jsonList);              //Returns the dataset                            return dsTable;        }        catch (Exception ex)        {            System.Windows.Forms.MessageBox.Show(ex.Message);            return null;        }    }       //deserializes the string to a list. Utilizes JSON.net. RootObject is a class that contains the get and set for the JSON elements    public List<RootObject> DeSerializeJsonString(string jsonString)    {          //Initialized the List        List<RootObject> list = new List<RootObject>();          //json.net deserializes string        list = (List<RootObject>)JsonConvert.DeserializeObject<List<RootObject>>(jsonString);        return list;    }

The RootObject contains the get set that will get the values of the JSON.

public class RootObject{        //These string will be set to the elements within the JSON. Each one is directly mapped to the JSON elements.      //This only takes into account a JSON that doesn't contain nested arrays    public string EntityID { get; set; }    public string Address1 { get; set; }    public string Address2 { get; set; }    public string Address3 { get; set; }}

The easiest way to create the above class(es) is to use json2charp which will format it accordingly and also provide the correct datatypes.

The following is from another answer on Stackoverflowagain it does not take into account nested JSON.

    internal static class ExtentsionHelpers{    public static DataSet ToDataSet<T>(this List<RootObject> list)    {        try        {            Type elementType = typeof(RootObject);            DataSet ds = new DataSet();            DataTable t = new DataTable();            ds.Tables.Add(t);            try            {                //add a column to table for each public property on T                foreach (var propInfo in elementType.GetProperties())                {                    try                    {                        Type ColType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;                            t.Columns.Add(propInfo.Name, ColType);                    }                    catch (Exception ex)                    {                        System.Windows.Forms.MessageBox.Show(ex.Message);                    }                }            }            catch (Exception ex)            {                System.Windows.Forms.MessageBox.Show(ex.Message);            }            try            {                //go through each property on T and add each value to the table                foreach (RootObject item in list)                {                    DataRow row = t.NewRow();                    foreach (var propInfo in elementType.GetProperties())                    {                        row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;                    }                    t.Rows.Add(row);                }            }            catch (Exception ex)            {                System.Windows.Forms.MessageBox.Show(ex.Message);            }            insert.insertCategories(t);            return ds.        }        catch (Exception ex)        {            System.Windows.Forms.MessageBox.Show(ex.Message);            return null;        }    }};

Then finally to insert the above dataset into a table with columns that were mapped to the JSON I utilized SQL bulk copy and the following class

public class insert{     public static string insertCategories(DataTable table)    {             SqlConnection objConnection = new SqlConnection();          //As specified in the App.config/web.config file        objConnection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["foo"].ToString();        try        {                                             objConnection.Open();            var bulkCopy = new SqlBulkCopy(objConnection.ConnectionString);            bulkCopy.DestinationTableName = "dbo.foo";            bulkCopy.BulkCopyTimeout = 600;            bulkCopy.WriteToServer(table);            return "";        }        catch (Exception ex)        {            System.Windows.Forms.MessageBox.Show(ex.Message);            return "";        }        finally        {            objConnection.Close();        }             }};

So the above works to insert JSON from a webAPI into a database. This is something that I get to work. But by no means do I expect it to be perfect. If you have any improvements then please update it accordingly.