Lesson 12 of 13

Files, JSON & HTTP

Learn to read and write files, convert objects to and from , and call an using .NET's built-in tools.

C#
using System.IO;
using System.Text;

// Whole-file helpers
await File.WriteAllTextAsync("notes.txt", "first line\nsecond line\n");
string content = await File.ReadAllTextAsync("notes.txt");
string[] lines = await File.ReadAllLinesAsync("notes.txt");
await File.AppendAllTextAsync("notes.txt", "third line\n");

// Streaming a large file — constant memory
await foreach (string line in File.ReadLinesAsync("huge.log"))
{
    if (line.Contains("ERROR")) Console.WriteLine(line);
}

// Writers and using declarations (disposed at end of scope)
using var writer = new StreamWriter("out.csv", append: false, Encoding.UTF8);
await writer.WriteLineAsync("id,name");
await writer.WriteLineAsync("1,Ada");

// Paths — never concatenate with "/" by hand
string path = Path.Combine(AppContext.BaseDirectory, "data", "report.csv");
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
Console.WriteLine(Path.GetExtension(path));       // .csv
Console.WriteLine(File.Exists(path));

foreach (var file in Directory.EnumerateFiles("data", "*.csv", SearchOption.AllDirectories))
    Console.WriteLine(file);
C#
using System.Text.Json;
using System.Text.Json.Serialization;

public record Todo(int Id, string Title, bool Completed)
{
    [JsonPropertyName("due_date")]
    public DateOnly? DueDate { get; init; }

    [JsonIgnore]
    public string Internal { get; init; } = "";
}

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = true,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};

var todo = new Todo(1, "Write docs", false) { DueDate = new DateOnly(2026, 9, 1) };

string json = JsonSerializer.Serialize(todo, options);
Console.WriteLine(json);

Todo? back = JsonSerializer.Deserialize<Todo>(json, options);

// Straight to and from a file, without building the whole string
await using (var fs = File.Create("todo.json"))
    await JsonSerializer.SerializeAsync(fs, todo, options);

await using (var fs = File.OpenRead("todo.json"))
{
    var loaded = await JsonSerializer.DeserializeAsync<Todo>(fs, options);
    Console.WriteLine(loaded?.Title);
}
C#
using System.Net.Http;
using System.Net.Http.Json;

// Create ONE HttpClient and reuse it. A new one per request exhausts sockets.
static readonly HttpClient Http = new()
{
    BaseAddress = new Uri("https://api.example.com/"),
    Timeout = TimeSpan.FromSeconds(10),
};

// GET and deserialize in one call
var todos = await Http.GetFromJsonAsync<List<Todo>>("todos");

// POST an object as JSON
var response = await Http.PostAsJsonAsync("todos", new Todo(0, "New task", false));
response.EnsureSuccessStatusCode();               // throws on 4xx/5xx
var created = await response.Content.ReadFromJsonAsync<Todo>();

// Full control plus cancellation
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var request = new HttpRequestMessage(HttpMethod.Get, "todos/1");
request.Headers.Add("Authorization", "Bearer token123");

try
{
    using var res = await Http.SendAsync(request, cts.Token);
    Console.WriteLine((int)res.StatusCode);
    Console.WriteLine(await res.Content.ReadAsStringAsync(cts.Token));
}
catch (TaskCanceledException)
{
    Console.WriteLine("request timed out");
}
Finished reading?Mark it done to track your progress.

Tip: use the ← and → keys to move between lessons.