简体   繁体   English

PostAsync 返回异常

[英]PostAsync returning exception

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.我正在使用控制台应用程序进行批量测试,在这些测试中,我调用了我在 API 中创建的 JobTitles 路由,在本例中是处理此路由的 controller。

For the Post function, which I am using, I made use of the HttpClient PostAsJsonAsync() method.对于我正在使用的 Post function,我使用了HttpClient PostAsJsonAsync()方法。 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.因为我已经在其他代码中使用了这个 function 我没有很多问题,但现在它返回异常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;我没有使用任何.Result调用,因为它可能最终导致死锁; I also tried using .ConfigureAwait (false) and it didn't work.我也尝试过使用.ConfigureAwait (false) ,但它没有用。 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.我也尝试使用Easy.Common RestClient()但发生了同样的错误,我已经没有关于错误可能是什么的选项了。 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 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.我尝试创建一个通用方法,因为在其他代码中我为每个实体创建了一个帖子,利用这个问题,我想知道除了 RestClient 和 HttpClient 之外是否还有另一个我可以用来发送多个调用而不会导致由于许多 API 条目而被取消的发货,因为它会自动取消以避免 DDoS。

And the stack trace I get from RestClient:我从 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 :编辑1

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.我只是发送一个请求只是为了测试它是否有效,我需要发送至少 x * 6 个 JobTitles 而不计算有更多的类要一起发送,所以我需要一种可以发送大量请求的方法API。

EDIT2 :编辑2

Stack Trace from HttpClient:来自 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:编辑3:

Main.cs:主要.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: 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: 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.与@Andy 讨论了对代码的几处更改,同样对我返回了相同的错误,我正在其他机器上进行测试并尝试通过 Insomnia 调用相同的路由以检查它是否尚未配置. For now it believes that it is the server preventing since I cannot return even an object response.目前它认为这是服务器阻止,因为我什至无法返回 object 响应。

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:编辑4:

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.经过这么多测试并使用不同的程序调用路由,我注意到这确实是服务器问题,更准确地说是 HTTP 认证,因为它是阻塞调用的那个。 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.我将对项目进行更改以获取更多信息,并在 edit5 中返回已决定的内容并发布答案以最终确定此问题。

So I believe your problem is on this line:所以我相信你的问题出在这条线上:

HttpResponseMessage response = await client.PostAsJsonAsync(route, 
    content).ConfigureAwait(false); //still not working            
if(!response.IsSuccessStatusCode)
{
    Console.WriteLine(content);
}

You haven't read anything yet.你还没有读到任何东西。 You just got the response object.您刚刚收到响应 object。 You have to do this with that response:您必须使用该响应执行此操作:

var objectReturned = await response.Content.ReadAsAsync<WhateverObject>();

or, to test:或者,测试:

var stringDataReturned = await response.Content.ReadAsStringAsync();

A typical scenario would look like this:一个典型的场景如下所示:

var response = await client.PostAsJsonAsync(route, content);
repsonse.EnsureSuccessStatusCode();

var data = await response.ReadAsStringAsync();
Console.WriteLine(data);

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.由于我使用 VSCode 进行编程,我没想到我应该对项目在本地运行后立即创建的.vscode文件夹进行任何更改。 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 .对于那些正在使用并出现错误Your connection is not private ,与Not secure相同的人,您必须从文件launch.jsonprogram.cs进行配置,我直接在launch.json进行了修改.

launch.json before modification:修改前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 after modification:修改后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"
    }
}

I just needed to add the line "ASPNETCORE_URLS": "http://localhost:5001" to remove the error of Not secure and the application ran correctly.我只需要添加行"ASPNETCORE_URLS": "http://localhost:5001"来删除 Not secure 的错误并且应用程序运行正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM