I'm using a Console App to do volume tests, in these tests I'm calling the JobTitles route that I created inside the API, in this case the controller that handles this route.
For the Post function, which I am using, I made use of the HttpClient PostAsJsonAsync()
method. As I already used this function in other code I didn't have many problems, but now it is returning the exception System.Net.Http.HttpRequestException: An error occurred while sending the request.
I'm not using any .Result
call as it may end up causing a deadlock; I also tried using .ConfigureAwait (false)
and it didn't work. I also tried to work with Easy.Common RestClient() but the same error occurs, I'm running out of options for what the error might be. I'm sorry but I can't figure out what the error is just by looking at the stack trace, I still didn't learn how figure it out.
I put the code here for better viewing as it is a little big:
https://repl.it/repls/JubilantMoccasinArrays
I tried to create a generic method since in the other code I made a Post for each Entity, taking advantage of the question, I would like to know if there is another one besides RestClient and HttpClient that I could use to send multiple calls without causing the shipments to be canceled due to many API entries, since it automatically cancels to avoid DDoS.
And the stack trace I get from RestClient:
Unhandled exception. System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The response ended prematurely.
at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at CodenApp.Studio2Me.VolumeTest.UsefulFunctions.HTTPFunctions`1.Post(String route, T content) in C:\Users\Yasmin Kruger\Documents\Studio2Me\Studio2Me\Tests\CodenApp.Studio2Me.VolumeTest\UsefulFunctions\HTTPFunctions.cs:line 29
at CodenApp.Studio2Me.VolumeTest.Classes.JobTitleData.JobTitleDataGenerator(Int32 x) in C:\Users\Yasmin Kruger\Documents\Studio2Me\Studio2Me\Tests\CodenApp.Studio2Me.VolumeTest\Classes\JobTitleData.cs:line 21
at CodenApp.Studio2Me.VolumeTest.Program.Main(String[] args) in C:\Users\Yasmin Kruger\Documents\Studio2Me\Studio2Me\Tests\CodenApp.Studio2Me.VolumeTest\Program.cs:line 22
at CodenApp.Studio2Me.VolumeTest.Program.<Main>(String[] args)
EDIT1:
I'm just sending one request just to test if it's working, I need to send at least x * 6 JobTitles without counting that there are more classes to send together, so I need a way that I can send a large amount of requests to the API.
EDIT2:
Stack Trace from HttpClient:
System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The response ended prematurely.
at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at CodenApp.Studio2Me.VolumeTest.UsefulFunctions.HTTPFunctions`1.PostTest(String route, T content) in C:\Users\Yasmin Kruger\Documents\Studio2Me\Studio2Me\Tests\CodenApp.Studio2Me.VolumeTest\UsefulFunctions\HTTPFunctions.cs:line 51
EDIT3:
Main.cs:
using System;
using CodenApp.Studio2Me.VolumeTest.Classes;
using CodenApp.Studio2Me.VolumeTest.UsefulFunctions;
namespace CodenApp.Studio2Me.VolumeTest
{
class Program
{
static async System.Threading.Tasks.Task Main(string[] args)
{
// await JobTitleData.JobTitleDataGenerator(1);
await JobTitleData.JobTitleDataGenerator2(1);
}
}
}
HTTPFunction.cs:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Easy.Common.Extensions;
using Easy.Common.Interfaces;
using Newtonsoft.Json;
using Shouldly;
using RestClient = Easy.Common.RestClient;
namespace CodenApp.Studio2Me.VolumeTest.UsefulFunctions
{
public class HTTPFunctions<T> where T : class
{
const string APIAddress = "http://localhost:5001/";
public static async Task Post(string route, T content)
{
var endpointUri = new Uri(APIAddress + route);
ServicePointManager.FindServicePoint(endpointUri).ConnectionLeaseTimeout.ShouldBe(-1);
var jsonContent = JsonConvert.SerializeObject(content);
var contentString = new StringContent(jsonContent, Encoding.UTF8, "application/json");
contentString.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using IRestClient client = new RestClient();
HttpResponseMessage response = await client.PostAsync(endpointUri, contentString); //This won't work too
//client.Timeout.ShouldBe(15.Seconds()); Sometimes cause an TimeOut Exception
Console.WriteLine(response);
}
public static async Task PostTest(string route, T content)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(APIAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage response = await client.PostAsJsonAsync(route, content).ConfigureAwait(false); //still not working
if(!response.IsSuccessStatusCode)
{
Console.WriteLine(content);
}
}
catch(Exception e)
{
//Using this just to get exception
Console.WriteLine(e.Message);
}
}
}
}
}
JobTitleData.cs:
using System;
using System.Threading.Tasks;
using Bogus;
using CodenApp.Studio2Me.Core.Entities.StoreEntities;
using CodenApp.Studio2Me.VolumeTest.UsefulFunctions;
namespace CodenApp.Studio2Me.VolumeTest.Classes
{
public class JobTitleData
{
public static async Task JobTitleDataGenerator(int x)
{
var faker = new Faker("pt_BR");
for(int i = 0; i < x; i++)
{
JobTitle jobTitle = new JobTitle();
jobTitle.Name = faker.Name.JobTitle();
jobTitle.StoreId = 1;
await HTTPFunctions<JobTitle>.Post("v1/Store/JobTitles", jobTitle);
}
}
public static async Task JobTitleDataGenerator2(int x)
{
var faker = new Faker("pt_BR");
for(int i = 0; i < x; i++)
{
JobTitle jobTitle = new JobTitle();
jobTitle.Name = faker.Name.JobTitle();
jobTitle.StoreId = 1;
await HTTPFunctions<JobTitle>.PostTest("v1/Store/JobTitles", jobTitle);
}
}
}
}
Several changes to the code were discussed with @Andy and the same returned the same error for me, I am doing the test on other machines and trying to call the same route through Insomnia to check if it is not something that has not been configured yet. For now it believes that it is the server preventing since I cannot return even an object response.
The changes proposed:
using (var msg = new HttpRequestMessage(HttpMethod.Post, new UriBuilder(APIAddress) { Path = route }.Uri))
{
msg.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
using (var resp = await _client.SendAsync(msg))
{
resp.EnsureSuccessStatusCode();
await resp.Content.ReadAsStringAsync();
}
}
}
}
EDIT4:
After so much testing and using different programs to call the route, I noticed that it was really a server problem, more precisely the HTTP certification, because it is the one that is blocking the call. I will make changes to the project for more information and in edit5 I return what was decided and post an answer to finalize this question.
After a long time I found out what the big problem was. Since I am using VSCode to program, I did not imagine that I should make any changes to the .vscode
folder that was created as soon as the project was run locally. For those who are using and appear the error Your connection is not private, which is the same as Not secure, you must make the configuration, either from the file launch.json
or program.cs
, I made the modification directly on launch.json
.
launch.json
before modification:
{
"name": ".NET Core Launch (api)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Src/CodenApp.Studio2Me.Api/bin/Debug/netcoreapp3.1/CodenApp.Studio2Me.Api.dll",
"args": [],
"cwd": "${workspaceFolder}/Src/CodenApp.Studio2Me.Api",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}
launch.json
after modification:
{
"name": ".NET Core Launch (api)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Src/CodenApp.Studio2Me.Api/bin/Debug/netcoreapp3.1/CodenApp.Studio2Me.Api.dll",
"args": [],
"cwd": "${workspaceFolder}/Src/CodenApp.Studio2Me.Api",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5001"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}
I just needed to add the line "ASPNETCORE_URLS": "http://localhost:5001"
to remove the error of Not secure and the application ran correctly.