C# System.Net

Network programming and web requests

🌐 What is System.Net?

System.Net provides classes for network communication and web requests. It enables your programs to download data from websites, make API calls, send emails, and communicate over networks using various protocols.


// Simple web request
using System.Net.Http;

HttpClient client = new HttpClient();
string result = await client.GetStringAsync("https://api.example.com");
                                    

Core System.Net Features

🌍

HttpClient

Make HTTP requests

var client = new HttpClient();
await client.GetStringAsync(url);
📥

WebClient

Download web content

var client = new WebClient();
client.DownloadFile(url, path);
🔌

TcpClient

TCP network connections

var client = new TcpClient();
client.Connect(host, port);
📧

SmtpClient

Send emails

var smtp = new SmtpClient();
smtp.Send(mailMessage);

🔹 HttpClient - Making Web Requests

HttpClient is the modern way to make HTTP requests in C#. Use it to call APIs, download web pages, and communicate with web services. It supports GET, POST, PUT, DELETE and other HTTP methods for complete web interaction.

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

class Program
{
    static async Task Main()
    {
        // Create HttpClient (reuse for multiple requests)
        using HttpClient client = new HttpClient();
        
        try
        {
            // GET request
            string url = "https://jsonplaceholder.typicode.com/posts/1";
            string response = await client.GetStringAsync(url);
            
            Console.WriteLine("Response:");
            Console.WriteLine(response);
            
            // GET with HttpResponseMessage
            HttpResponseMessage result = await client.GetAsync(url);
            
            Console.WriteLine($"\nStatus Code: {result.StatusCode}");
            Console.WriteLine($"Success: {result.IsSuccessStatusCode}");
            
            // Read content
            string content = await result.Content.ReadAsStringAsync();
            Console.WriteLine($"Content Length: {content.Length} characters");
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Output:

Response:

{

"userId": 1,

"id": 1,

"title": "Sample Post"

}

Status Code: OK

Success: True

Content Length: 292 characters

🔹 POST Requests with HttpClient

POST requests send data to web servers, commonly used for submitting forms, creating resources, or sending JSON data to APIs. HttpClient makes it easy to send different content types and handle responses.

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using HttpClient client = new HttpClient();
        
        try
        {
            // Prepare JSON data
            string jsonData = @"{
                ""title"": ""My Post"",
                ""body"": ""This is the content"",
                ""userId"": 1
            }";
            
            // Create content
            StringContent content = new StringContent(
                jsonData,
                Encoding.UTF8,
                "application/json"
            );
            
            // POST request
            string url = "https://jsonplaceholder.typicode.com/posts";
            HttpResponseMessage response = await client.PostAsync(url, content);
            
            Console.WriteLine($"Status: {response.StatusCode}");
            
            // Read response
            string result = await response.Content.ReadAsStringAsync();
            Console.WriteLine("\nResponse:");
            Console.WriteLine(result);
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Output:

Status: Created

Response:

{

"title": "My Post",

"body": "This is the content",

"userId": 1,

"id": 101

}

🔹 WebClient - Simple Downloads

WebClient provides simple methods for downloading files and web content. While HttpClient is preferred for new code, WebClient is still useful for quick downloads and simple scenarios where you need straightforward file retrieval.

using System;
using System.Net;

class Program
{
    static void Main()
    {
        using WebClient client = new WebClient();
        
        try
        {
            // Download string
            string url = "https://jsonplaceholder.typicode.com/posts/1";
            string content = client.DownloadString(url);
            
            Console.WriteLine("Downloaded content:");
            Console.WriteLine(content.Substring(0, 100) + "...");
            
            // Download file
            string fileUrl = "https://example.com/sample.txt";
            string savePath = "downloaded.txt";
            // client.DownloadFile(fileUrl, savePath);
            // Console.WriteLine($"\nFile saved to: {savePath}");
            
            // Download data as bytes
            byte[] data = client.DownloadData(url);
            Console.WriteLine($"\nDownloaded {data.Length} bytes");
            
            // Upload string (POST)
            string postUrl = "https://jsonplaceholder.typicode.com/posts";
            string postData = "title=Test&body=Content";
            string response = client.UploadString(postUrl, postData);
            
            Console.WriteLine("\nUpload response received");
        }
        catch (WebException e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Output:

Downloaded content:

{

"userId": 1,

"id": 1,

"title": "sunt aut facere..."

Downloaded 292 bytes

Upload response received

🔹 Working with Headers

HTTP headers carry important information about requests and responses. You can add custom headers for authentication, specify content types, set user agents, and read response headers to understand server responses better.

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

class Program
{
    static async Task Main()
    {
        using HttpClient client = new HttpClient();
        
        // Add default headers
        client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
        client.DefaultRequestHeaders.Add("Accept", "application/json");
        
        // Add authorization header
        client.DefaultRequestHeaders.Add("Authorization", "Bearer token123");
        
        Console.WriteLine("Request Headers:");
        foreach (var header in client.DefaultRequestHeaders)
        {
            Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
        }
        
        try
        {
            string url = "https://jsonplaceholder.typicode.com/posts/1";
            HttpResponseMessage response = await client.GetAsync(url);
            
            Console.WriteLine("\nResponse Headers:");
            foreach (var header in response.Headers)
            {
                Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
            }
            
            Console.WriteLine($"\nContent Type: {response.Content.Headers.ContentType}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Output:

Request Headers:

User-Agent: MyApp/1.0

Accept: application/json

Authorization: Bearer token123

Response Headers:

Date: Mon, 06 Oct 2025 14:30:00 GMT

Server: cloudflare

Content Type: application/json; charset=utf-8

🔹 DNS and IP Addresses

The Dns class helps you work with domain names and IP addresses. You can resolve hostnames to IP addresses, get information about network hosts, and perform reverse DNS lookups for network diagnostics and tools.

using System;
using System.Net;

class Program
{
    static void Main()
    {
        try
        {
            // Get host name
            string hostName = Dns.GetHostName();
            Console.WriteLine($"Host Name: {hostName}");
            
            // Get host entry
            IPHostEntry hostEntry = Dns.GetHostEntry(hostName);
            Console.WriteLine($"\nHost: {hostEntry.HostName}");
            
            // Display IP addresses
            Console.WriteLine("\nIP Addresses:");
            foreach (IPAddress ip in hostEntry.AddressList)
            {
                Console.WriteLine($"- {ip} ({ip.AddressFamily})");
            }
            
            // Resolve domain name
            string domain = "google.com";
            IPHostEntry googleEntry = Dns.GetHostEntry(domain);
            
            Console.WriteLine($"\n{domain} IP Addresses:");
            foreach (IPAddress ip in googleEntry.AddressList)
            {
                Console.WriteLine($"- {ip}");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Output:

Host Name: DESKTOP-ABC123

Host: DESKTOP-ABC123

IP Addresses:

- 192.168.1.100 (InterNetwork)

- fe80::1234:5678 (InterNetworkV6)

google.com IP Addresses:

- 142.250.185.46

- 2607:f8b0:4004:c07::71

🔹 Error Handling

Error handling in C# is managed using try-catch blocks to gracefully manage unexpected runtime exceptions. The try block contains code that might throw an error, while the catch block captures and handles specific or general exceptions, preventing application crashes. For example, when an HTTP request fails with a 500 Internal Server Error, catch blocks can log the error, display a user-friendly message, or implement retry logic. This ensures robustness and improves user experience by handling failures predictively.

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

class Program
{
    static async Task Main()
    {
        using HttpClient client = new HttpClient();
        client.Timeout = TimeSpan.FromSeconds(5);
        
        string[] urls = {
            "https://jsonplaceholder.typicode.com/posts/1",
            "https://invalid-url-that-does-not-exist.com",
            "https://httpstat.us/500"
        };
        
        foreach (string url in urls)
        {
            try
            {
                Console.WriteLine($"\nTrying: {url}");
                HttpResponseMessage response = await client.GetAsync(url);
                
                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine($"✓ Success: {response.StatusCode}");
                }
                else
                {
                    Console.WriteLine($"✗ Failed: {response.StatusCode}");
                }
            }
            catch (HttpRequestException e)
            {
                Console.WriteLine($"✗ Request Error: {e.Message}");
            }
            catch (TaskCanceledException)
            {
                Console.WriteLine("✗ Timeout: Request took too long");
            }
            catch (Exception e)
            {
                Console.WriteLine($"✗ Error: {e.Message}");
            }
        }
    }
}

Output:

Trying: https://jsonplaceholder.typicode.com/posts/1

✓ Success: OK

Trying: https://invalid-url-that-does-not-exist.com

✗ Request Error: No such host is known

Trying: https://httpstat.us/500

✗ Failed: InternalServerError

🧠 Test Your Knowledge

Which class is recommended for making HTTP requests in modern C#?