From 4433f9283d0c772f78028176c9f1a248104b15da Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 11 Oct 2026 12:24:13 +0200 Subject: [PATCH] HttpClient vs RestSharp: .NET 10, RestSharp 114.0.0, PutAsJsonAsync, LiveTests - Retarget both projects from net6.0 to net10.0 (RestSharp 114.0.0 ships no net6.0 or net7.0 asset) - RestSharp 108.0.1 to 114.0.0, BenchmarkDotNet 0.13.1 to 0.15.8 - Tests: Microsoft.NET.Test.Sdk 18.10.1, xunit 2.9.3, xunit.runner.visualstudio 4.0.1, coverlet.collector 10.1.0 - UpdateTodo_HttpClient uses PutAsJsonAsync; unused System.Text and System.Text.Json usings removed - Field initializers are target-typed and set BaseAddress, so the constructor is gone - Tests renamed to LiveTests (they call jsonplaceholder.typicode.com), with tests for GetFromJsonAsync, ExecuteGetAsync, a 404 on both clients, HttpClient.Send and RestClient.Get --- .../HttpClientVsRestSharp.csproj | 6 +- .../HttpClientVsRestSharp/TodoBenchmark.cs | 16 +--- .../Tests/{Tests.cs => LiveTests.cs} | 94 ++++++++++++++++++- .../HttpClientVsRestSharp/Tests/Tests.csproj | 10 +- 4 files changed, 104 insertions(+), 22 deletions(-) rename dotnet-client-libraries/HttpClientVsRestSharp/Tests/{Tests.cs => LiveTests.cs} (63%) diff --git a/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/HttpClientVsRestSharp.csproj b/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/HttpClientVsRestSharp.csproj index 472c72f87f..8924b88cbd 100644 --- a/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/HttpClientVsRestSharp.csproj +++ b/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/HttpClientVsRestSharp.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net10.0 enable enable false @@ -10,8 +10,8 @@ - - + + diff --git a/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/TodoBenchmark.cs b/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/TodoBenchmark.cs index 296b8a0cd5..893a34e97a 100644 --- a/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/TodoBenchmark.cs +++ b/dotnet-client-libraries/HttpClientVsRestSharp/HttpClientVsRestSharp/TodoBenchmark.cs @@ -1,21 +1,14 @@ using BenchmarkDotNet.Attributes; using RestSharp; using System.Net.Http.Json; -using System.Text; -using System.Text.Json; namespace HttpClientVsRestSharp { [MemoryDiagnoser] public class TodoBenchmark { - private static readonly HttpClient httpClient = new HttpClient(); - private static readonly RestClient restClient = new RestClient("https://jsonplaceholder.typicode.com/"); - - public TodoBenchmark() - { - httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); - } + private static readonly HttpClient httpClient = new() { BaseAddress = new Uri("https://jsonplaceholder.typicode.com/") }; + private static readonly RestClient restClient = new("https://jsonplaceholder.typicode.com/"); [Benchmark] public async Task?> GetAllTodos_HttpClient() @@ -62,10 +55,7 @@ public TodoBenchmark() { var todoForUpdate = GetTodoForUpdate(); - var serializedTodo = JsonSerializer.Serialize(todoForUpdate); - var requestContent = new StringContent(serializedTodo, Encoding.UTF8, "application/json"); - - var response = await httpClient.PutAsync($"todos/{todoForUpdate.Id}", requestContent); + var response = await httpClient.PutAsJsonAsync($"todos/{todoForUpdate.Id}", todoForUpdate); var updatedTodo = await response.Content.ReadFromJsonAsync(); return updatedTodo; diff --git a/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.cs b/dotnet-client-libraries/HttpClientVsRestSharp/Tests/LiveTests.cs similarity index 63% rename from dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.cs rename to dotnet-client-libraries/HttpClientVsRestSharp/Tests/LiveTests.cs index 8580748c08..3c09e2023a 100644 --- a/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.cs +++ b/dotnet-client-libraries/HttpClientVsRestSharp/Tests/LiveTests.cs @@ -2,6 +2,7 @@ using RestSharp; using System; using System.Collections.Generic; +using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Text; @@ -11,7 +12,7 @@ namespace Tests { - public class Tests + public class LiveTests { [Fact] @@ -145,6 +146,97 @@ public async Task GivenRestSharp_WhenDeletingTodo_ThenResponseIsSuccessful() Assert.True(response.IsSuccessful); } + [Fact] + public async Task GivenHttpClient_WhenGettingTodosWithGetFromJsonAsync_ThenReturnsListOfTodos() + { + //Arrange + var httpClient = new HttpClient(); + httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); + + //Act + var todos = await httpClient.GetFromJsonAsync>("todos"); + + //Assert + Assert.NotNull(todos); + Assert.NotEmpty(todos); + } + + [Fact] + public async Task GivenRestSharp_WhenExecutingGetForTodos_ThenResponseIsSuccessful() + { + //Arrange + var restClient = new RestClient("https://jsonplaceholder.typicode.com/"); + var request = new RestRequest("todos"); + + //Act + var response = await restClient.ExecuteGetAsync>(request); + + //Assert + Assert.True(response.IsSuccessful); + Assert.NotNull(response.Data); + Assert.NotEmpty(response.Data); + } + + [Fact] + public async Task GivenHttpClient_WhenPathDoesNotExist_ThenEnsureSuccessStatusCodeThrows() + { + //Arrange + var httpClient = new HttpClient(); + httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); + + //Act + var response = await httpClient.GetAsync("no-such-path"); + + //Assert + Assert.False(response.IsSuccessStatusCode); + Assert.Throws(() => response.EnsureSuccessStatusCode()); + } + + [Fact] + public async Task GivenRestSharp_WhenPathDoesNotExist_ThenResponseIsNotSuccessfulAndNothingThrows() + { + //Arrange + var restClient = new RestClient("https://jsonplaceholder.typicode.com/"); + var request = new RestRequest("no-such-path"); + + //Act + var response = await restClient.ExecuteGetAsync(request); + + //Assert + Assert.False(response.IsSuccessful); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + [Fact] + public void GivenHttpClient_WhenSendingSynchronously_ThenResponseIsSuccessStatusCode() + { + //Arrange + var httpClient = new HttpClient(); + httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/"); + var request = new HttpRequestMessage(HttpMethod.Get, "todos"); + + //Act + var response = httpClient.Send(request); + + //Assert + Assert.True(response.IsSuccessStatusCode); + } + + [Fact] + public void GivenRestSharp_WhenGettingTodosSynchronously_ThenReturnsListOfTodos() + { + //Arrange + var restClient = new RestClient("https://jsonplaceholder.typicode.com/"); + var request = new RestRequest("todos"); + + //Act + var todos = restClient.Get>(request); + + //Assert + Assert.NotNull(todos); + Assert.NotEmpty(todos); + } + private static Todo GetTodoForCreation() { return new Todo diff --git a/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.csproj b/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.csproj index c225f9fc79..3b78716b5d 100644 --- a/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.csproj +++ b/dotnet-client-libraries/HttpClientVsRestSharp/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 enable false false @@ -9,13 +9,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all