PostAsync 返回异常
PostAsync returning exception
我正在使用控制台应用程序进行音量测试,在这些测试中,我调用了我在 API 中创建的 JobTitles 路由,在本例中是处理该路由的控制器。
对于我正在使用的 Post 函数,我使用了 HttpClient PostAsJsonAsync()
方法。因为我已经在其他代码中使用过这个函数,所以我没有遇到太多问题,但现在它是 returning 异常 System.Net.Http.HttpRequestException: An error occurred while sending the request.
我没有使用任何 .Result
调用,因为它最终可能会导致死锁;我也尝试使用 .ConfigureAwait (false)
但它没有用。我也尝试使用 Easy.Common RestClient() 但同样的错误发生了,我 运行 无法选择错误可能是什么。很抱歉,我无法通过查看堆栈跟踪来弄清楚错误是什么,我仍然没有学会如何弄清楚。
我把代码放在这里是为了更好看,因为它有点大:
https://repl.it/repls/JubilantMoccasinArrays
我试图创建一个通用方法,因为在其他代码中我为每个实体创建了一个 Post,利用这个问题,我想知道除了 RestClient 和 HttpClient 之外是否还有另一个我可以用来发送多个电话,而不会由于许多 API 条目而导致发货被取消,因为它会自动取消以避免 DDoS。
以及我从 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:
我只是发送一个请求只是为了测试它是否有效,我需要发送至少 x * 6 个 JobTitles 而不计算还有更多 类 一起发送,所以我需要一种方法我可以向 API.
发送大量请求
EDIT2:
来自 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
编辑3:
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);
}
}
}
}
与@Andy 讨论了对代码的几处更改,同样 return 对我来说同样的错误,我正在其他机器上进行测试并尝试通过 Insomnia 调用相同的路由来检查是否它不是尚未配置的东西。现在它认为它是服务器阻止,因为我无法 return 甚至对象响应。
提议的修改:
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:
经过多次测试并使用不同程序调用路由后,我发现这确实是服务器问题,更确切地说是 HTTP 认证问题,因为它是阻止调用的问题。我将对项目进行更改以获取更多信息,在 edit5 中我 return 决定了什么,post 一个答案来最终确定这个问题。
所以我认为您的问题出在这一行:
HttpResponseMessage response = await client.PostAsJsonAsync(route,
content).ConfigureAwait(false); //still not working
if(!response.IsSuccessStatusCode)
{
Console.WriteLine(content);
}
您还没有阅读任何内容。你刚刚得到了响应对象。您必须对该响应执行此操作:
var objectReturned = await response.Content.ReadAsAsync<WhateverObject>();
或者,测试:
var stringDataReturned = await response.Content.ReadAsStringAsync();
一个典型的场景是这样的:
var response = await client.PostAsJsonAsync(route, content);
repsonse.EnsureSuccessStatusCode();
var data = await response.ReadAsStringAsync();
Console.WriteLine(data);
经过很长一段时间,我发现了大问题。由于我是用VSCode来编程的,所以我没想到我应该对项目在本地运行时创建的.vscode
文件夹进行任何更改。对于那些正在使用并出现Your connection is not private错误的人,这与Not secure相同,您必须进行配置,或者从文件 launch.json
或 program.cs
中,我直接在 launch.json
.
上进行了修改
launch.json
修改前:
{
"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
修改后:
{
"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"
}
}
我只需要添加行 "ASPNETCORE_URLS": "http://localhost:5001"
来删除不安全的错误和应用程序 运行 正确。
我正在使用控制台应用程序进行音量测试,在这些测试中,我调用了我在 API 中创建的 JobTitles 路由,在本例中是处理该路由的控制器。
对于我正在使用的 Post 函数,我使用了 HttpClient PostAsJsonAsync()
方法。因为我已经在其他代码中使用过这个函数,所以我没有遇到太多问题,但现在它是 returning 异常 System.Net.Http.HttpRequestException: An error occurred while sending the request.
我没有使用任何 .Result
调用,因为它最终可能会导致死锁;我也尝试使用 .ConfigureAwait (false)
但它没有用。我也尝试使用 Easy.Common RestClient() 但同样的错误发生了,我 运行 无法选择错误可能是什么。很抱歉,我无法通过查看堆栈跟踪来弄清楚错误是什么,我仍然没有学会如何弄清楚。
我把代码放在这里是为了更好看,因为它有点大:
https://repl.it/repls/JubilantMoccasinArrays
我试图创建一个通用方法,因为在其他代码中我为每个实体创建了一个 Post,利用这个问题,我想知道除了 RestClient 和 HttpClient 之外是否还有另一个我可以用来发送多个电话,而不会由于许多 API 条目而导致发货被取消,因为它会自动取消以避免 DDoS。
以及我从 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:
我只是发送一个请求只是为了测试它是否有效,我需要发送至少 x * 6 个 JobTitles 而不计算还有更多 类 一起发送,所以我需要一种方法我可以向 API.
发送大量请求EDIT2:
来自 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
编辑3:
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);
}
}
}
}
与@Andy 讨论了对代码的几处更改,同样 return 对我来说同样的错误,我正在其他机器上进行测试并尝试通过 Insomnia 调用相同的路由来检查是否它不是尚未配置的东西。现在它认为它是服务器阻止,因为我无法 return 甚至对象响应。
提议的修改:
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:
经过多次测试并使用不同程序调用路由后,我发现这确实是服务器问题,更确切地说是 HTTP 认证问题,因为它是阻止调用的问题。我将对项目进行更改以获取更多信息,在 edit5 中我 return 决定了什么,post 一个答案来最终确定这个问题。
所以我认为您的问题出在这一行:
HttpResponseMessage response = await client.PostAsJsonAsync(route,
content).ConfigureAwait(false); //still not working
if(!response.IsSuccessStatusCode)
{
Console.WriteLine(content);
}
您还没有阅读任何内容。你刚刚得到了响应对象。您必须对该响应执行此操作:
var objectReturned = await response.Content.ReadAsAsync<WhateverObject>();
或者,测试:
var stringDataReturned = await response.Content.ReadAsStringAsync();
一个典型的场景是这样的:
var response = await client.PostAsJsonAsync(route, content);
repsonse.EnsureSuccessStatusCode();
var data = await response.ReadAsStringAsync();
Console.WriteLine(data);
经过很长一段时间,我发现了大问题。由于我是用VSCode来编程的,所以我没想到我应该对项目在本地运行时创建的.vscode
文件夹进行任何更改。对于那些正在使用并出现Your connection is not private错误的人,这与Not secure相同,您必须进行配置,或者从文件 launch.json
或 program.cs
中,我直接在 launch.json
.
launch.json
修改前:
{
"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
修改后:
{
"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"
}
}
我只需要添加行 "ASPNETCORE_URLS": "http://localhost:5001"
来删除不安全的错误和应用程序 运行 正确。