繁体   English   中英

PostAsync 返回异常

[英]PostAsync returning exception

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

对于我正在使用的 Post function,我使用了HttpClient PostAsJsonAsync()方法。 因为我已经在其他代码中使用了这个 function 我没有很多问题,但现在它返回异常System.Net.Http.HttpRequestException: An error occurred while sending the request.

我没有使用任何.Result调用,因为它可能最终导致死锁; 我也尝试过使用.ConfigureAwait (false) ,但它没有用。 我也尝试使用Easy.Common RestClient()但发生了同样的错误,我已经没有关于错误可能是什么的选项了。 很抱歉,但我无法通过查看堆栈跟踪来弄清楚错误是什么,我仍然没有学会如何弄清楚。

我把代码放在这里以便更好地查看,因为它有点大:

https://repl.it/repls/JubilantMoccasinArrays

我尝试创建一个通用方法,因为在其他代码中我为每个实体创建了一个帖子,利用这个问题,我想知道除了 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)

编辑1

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

编辑2

来自 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:

主要.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 讨论了对代码的几处更改,同样对我返回了相同的错误,我正在其他机器上进行测试并尝试通过 Insomnia 调用相同的路由以检查它是否尚未配置. 目前它认为这是服务器阻止,因为我什至无法返回 object 响应。

提议的更改:

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();
            }
        }
    }
}

编辑4:

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

所以我相信你的问题出在这条线上:

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

你还没有读到任何东西。 您刚刚收到响应 object。 您必须使用该响应执行此操作:

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.jsonprogram.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"来删除 Not secure 的错误并且应用程序运行正确。

暂无
暂无

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

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