[c#] How to properly make a http web GET request

i am still new on c# and i'm trying to create an application for this page that will tell me when i get a notification (answered, commented, etc..). But for now i'm just trying to make a simple call to the api which will get the user's data.

i'm using Visual studio express 2012 to build the C# application, where (for now) you enter your user id, so the application will make the request with the user id and show the stats of this user id.

here is the code where i'm trying to make the request:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Request library
using System.Net;
using System.IO;

namespace TestApplication
{
    class Connect
    {
        public string id;
        public string type;

        protected string api = "https://api.stackexchange.com/2.2/";
        protected string options = "?order=desc&sort=name&site=stackoverflow";

        public string request()
        {
            string totalUrl = this.join(id);

            return this.HttpGet(totalUrl);
        }

        protected string join(string s)
        {
            return api + type + "/" + s + options;
        }

        protected string get(string url)
        {
            try
            {
                string rt;

                WebRequest request = WebRequest.Create(url);

                WebResponse response = request.GetResponse();

                Stream dataStream = response.GetResponseStream();

                StreamReader reader = new StreamReader(dataStream);

                rt = reader.ReadToEnd();

                Console.WriteLine(rt);

                reader.Close();
                response.Close();

                return rt;
            }

            catch(Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }
        public string HttpGet(string URI)
        {
            WebClient client = new WebClient();

            // Add a user agent header in case the 
            // requested URI contains a query.

            client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

            Stream data = client.OpenRead(URI);
            StreamReader reader = new StreamReader(data);
            string s = reader.ReadToEnd();
            data.Close();
            reader.Close();

            return s;
        }
    }
}

the class is an object and its being accessed from the form by just parsing it the user id and make the request.

i have tried many of the examples i have looked on google, but not clue why i am getting on all ways this message "?".

i am new in this kind of algorithm, if anyone can share a book or tutorial that shows how to do this kind of stuff (explaining each step), i would appreciate it

This question is related to c# .net httpwebrequest

The answer is


Servers sometimes compress their responses to save on bandwidth, when this happens, you need to decompress the response before attempting to read it. Fortunately, the .NET framework can do this automatically, however, we have to turn the setting on.

Here's an example of how you could achieve that.

string html = string.Empty;
string url = @"https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
    html = reader.ReadToEnd();
}

Console.WriteLine(html);

GET

public string Get(string uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

GET async

public async Task<string> GetAsync(string uri)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

    using(HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return await reader.ReadToEndAsync();
    }
}

POST
Contains the parameter method in the event you wish to use other HTTP methods such as PUT, DELETE, ETC

public string Post(string uri, string data, string contentType, string method = "POST")
{
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    request.ContentLength = dataBytes.Length;
    request.ContentType = contentType;
    request.Method = method;

    using(Stream requestBody = request.GetRequestStream())
    {
        requestBody.Write(dataBytes, 0, dataBytes.Length);
    }

    using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return reader.ReadToEnd();
    }
}

    

POST async
Contains the parameter method in the event you wish to use other HTTP methods such as PUT, DELETE, ETC

public async Task<string> PostAsync(string uri, string data, string contentType, string method = "POST")
{
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    request.ContentLength = dataBytes.Length;
    request.ContentType = contentType;
    request.Method = method;

    using(Stream requestBody = request.GetRequestStream())
    {
        await requestBody.WriteAsync(dataBytes, 0, dataBytes.Length);
    }

    using(HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    using(Stream stream = response.GetResponseStream())
    using(StreamReader reader = new StreamReader(stream))
    {
        return await reader.ReadToEndAsync();
    }
}

Simpliest way for my opinion

  var web = new WebClient();
  var url = $"{hostname}/LoadDataSync?systemID={systemId}";
  var responseString = web.DownloadString(url);

OR

 var bytes = web.DownloadData(url);

Adding to the responses already given, this is a complete example hitting JSON PlaceHolder site.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Publish
{
    class Program
    {
        static async Task Main(string[] args)
        {
            
            // Get Reqeust
            HttpClient req = new HttpClient();
            var content = await req.GetAsync("https://jsonplaceholder.typicode.com/users");
            Console.WriteLine(await content.Content.ReadAsStringAsync());

            // Post Request
            Post p = new Post("Some title", "Some body", "1");
            HttpContent payload = new StringContent(JsonConvert.SerializeObject(p));
            content = await req.PostAsync("https://jsonplaceholder.typicode.com/posts", payload);
            Console.WriteLine("--------------------------");
            Console.WriteLine(content.StatusCode);
            Console.WriteLine(await content.Content.ReadAsStringAsync());
        }
    }

    public struct Post {
        public string Title {get; set;}
        public string Body {get;set;}
        public string UserID {get; set;}

        public Post(string Title, string Body, string UserID){
            this.Title = Title;
            this.Body = Body;
            this.UserID = UserID;
        }
    }
}

Another way is using 'HttpClient' like this:

using System;
using System.Net;
using System.Net.Http;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Making API Call...");
            using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
            {
                client.BaseAddress = new Uri("https://api.stackexchange.com/2.2/");
                HttpResponseMessage response = client.GetAsync("answers?order=desc&sort=activity&site=stackoverflow").Result;
                response.EnsureSuccessStatusCode();
                string result = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Result: " + result);
            }
            Console.ReadLine();
        }
    }
}

Check HttpClient vs HttpWebRequest from stackoverflow and this from other.

Update June 22, 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);
   }
   client.BaseAddress = new Uri("https://api.stackexchange.com/2.2/");
   HttpResponseMessage response = client.GetAsync("answers?order=desc&sort=activity&site=stackoverflow").Result;
   response.EnsureSuccessStatusCode();
   string result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine("Result: " + result);           
 }

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);

var request = (HttpWebRequest)WebRequest.Create("sendrequesturl");
var response = (HttpWebResponse)request.GetResponse();
string responseString;
using (var stream = response.GetResponseStream())
{
    using (var reader = new StreamReader(stream))
    {
        responseString = reader.ReadToEnd();
    }
}

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to httpwebrequest

C# HttpWebRequest The underlying connection was closed: An unexpected error occurred on a send How to properly make a http web GET request Send JSON via POST in C# and Receive the JSON returned? How to create JSON post to api using C# Use C# HttpWebRequest to send json to web service Post form data using HttpWebRequest HttpWebRequest-The remote server returned an error: (400) Bad Request Get host domain from URL? How to ignore the certificate check when ssl Receiving JSON data back from HTTP request