我正在使用 Polly 重试 HttpClient 尝试:
\n services.AddHttpClient<JoinPackageApiClient>(jp => { jp.BaseAddress = new Uri(appSettings.JoinPackageWS.BaseUrl); })\n .AddPolicyHandler(GetRetryPolicy(appSettings, serviceProvider))\nRun Code Online (Sandbox Code Playgroud)\n哪里 GetRetryPolicy:
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(AppSettings appSettings, ServiceProvider serviceProvider)\n {\n return HttpPolicyExtensions\n .HandleTransientHttpError()\n .OrResult(msg => msg.StatusCode != HttpStatusCode.OK)\n .Or<TimeoutRejectedException>()\n .Or<TaskCanceledException>()\n .Or<OperationCanceledException>()\n\n .WaitAndRetryAsync(appSettings.PollySettings.RetryAttempts, (retryAttempt, c) =>\n {\n\n return TimeSpan.FromSeconds(2);\n }, onRetry: (response, delay, retryCount, context) =>\n {\n\n //\xe2\x96\x88how can I access the full(!) HttpClient's URI here ?\n //e.g. : https://a.com/b/c?d=1\n \n });\n }\nRun Code Online (Sandbox Code Playgroud)\n问题:
\n查看该onRetry参数,我想在该onRetry部分中记录完整的 URL …
我并不是真正的 C# 专家,我有一个 C# 中的 post httpRequest 需要开发,为此我创建了这个方法,它接受一个 Uri、一个对象和一个不记名令牌。
该方法旨在构建调用请求:
private HttpClient client = new HttpClient();
public async Task<UserResponse> CreateUser(Uri url, UserRequest userRequest, string token)
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
string requestObject = JsonConvert.SerializeObject(userRequest);
Console.WriteLine("My Object: " + requestObject);
var req = new HttpRequestMessage(HttpMethod.Post, url);
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
req.Content = new StringContent(
requestObject,
Encoding.UTF8,
"application/json"
);
Console.WriteLine(req.ToString());
var response = await client.SendAsync(req);
string output = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.DeserializeObject(output));
UserResponse returnValue = JsonConvert.DeserializeObject<UserResponse>(output);
return returnValue;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我不确定我是否正确传递了标题内容。返回响应是一条错误消息,告诉我没有经过身份验证。
谢谢
我将 Polly ( Microsoft.Extensions.Http.Polly) 与 .net core 一起使用,并进行此配置(使用无效的 URL,用于测试):
private static void RegisterServices()
{
var collection = new ServiceCollection();
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(2); // Timeout for an individual try
collection.AddHttpClient<INetworkService, NetworkService>(url=>
{
url.BaseAddress = new Uri("http://www.google.com:81"); //test bad url
})
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(timeoutPolicy); ;
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
哪里GetRetryPolicy:
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode != HttpStatusCode.OK)
.Or<TimeoutRejectedException>()
.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.WaitAndRetryAsync(3, retryAttempt =>
{
return TimeSpan.FromSeconds(2);
},
onRetry: (response, delay, retryCount, context) => …Run Code Online (Sandbox Code Playgroud) 我需要检测何时存在重定向。我的第一个想法是检查 301 的状态代码,但是:
var link = "https://grnh.se/8dc368b82us?s=LinkedIn&source=LinkedIn";
var responseMessage = await httpClient.GetAsync(link);
Run Code Online (Sandbox Code Playgroud)
responseMessage 返回“OK”,但在浏览器中此链接返回 301 并重定向。
因此,如果我不能依赖于此,那么我决定只将请求 URI 与响应 URI 进行比较。
GetAsync 返回一个,Task<HttpResponseMessage>但 HttpResponseMessage没有响应 URI 的属性。
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpresponsemessage?view=net-5.0
System.Net.WebResponse 包含响应 URI 的属性,但我可以将其与 HttpClient 一起使用吗?或者我必须使用 WebRequest 来请求?
https://learn.microsoft.com/en-us/dotnet/api/system.net.webresponse?view=net-5.0
有没有更好的办法?
注意:这将扫描数百万个链接,因此我更愿意实例化一个 HttpClient。Microsoft 建议使用 HttpClient 而不是 WebRequest: https://learn.microsoft.com/en-us/dotnet/api/system.net.webresponse ?view=net-5.0
WebApplicationFactory我正在尝试创建一组(大部分)统一的集成测试,这些测试可以针对从我们的应用程序的完全部署版本创建的内存中 API 。使用XUnit.DependencyInjection,我计划将 a 注入HttpClient到我的测试中,该测试要么指向测试服务器,要么基于环境变量指向真实的应用程序。
因此,要为测试服务器创建客户端,我可以在以下位置运行以下命令Startup.cs:
WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();
Run Code Online (Sandbox Code Playgroud)
这似乎有效。但是,我完全不知道如何将此实现注入到HttpClient各个测试类中。
像这样的东西不起作用(这样的重载不存在):
services.AddHttpClient<MyTestClass>(client);
Run Code Online (Sandbox Code Playgroud)
这也不是(注入的客户端BaseAddress由于某种原因设置为 null):
services.AddHttpClient<InMemoryServerSelfTests>(c =>
{
c.BaseAddress = client.BaseAddress;
c.Timeout = client.Timeout;
});
Run Code Online (Sandbox Code Playgroud)
我唯一的另一个想法是创建一个新类来包装两个客户端并注入它,但这看起来很混乱:
public class TestClientWrapper
{
public readonly HttpClient Client;
public TestClientWrapper(InMemoryTestServer server)
{
Client = server.CreateClient();
}
public TestClientWrapper(HttpClient client)
{
Client = client;
}
}
// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
string targetEndpoint = Environment.GetEnvironmentVariable("targetEndpoint"); // Make …Run Code Online (Sandbox Code Playgroud) 我正在使用HttpClient异步向外部api发出许多请求.我等待所有请求完成,然后在其他代码中使用响应.我的问题是,如果我发出太多请求,当我使用Task.WhenAll等待时,我的代码会引发异常.
这段代码最终将并行运行,我的意思是我将同时执行多组这些异步请求(即10组200个异步请求).我已经实例化了一个HttpClient,我正在使用.NET 4.5异步/等待修饰符,如下所示:
using (var client = new HttpClient())
{
// make a list of tasks
List<Task<HttpResponseMessage>> taskList;
List<MyData> replies;
for (int i = 0; i < MAX_NUMBER_REQUESTS; i++)
{
taskList.Add(client.GetAsync(externalUri);
}
List<HttpResponseMessage> responses = await Task.WhenAll(taskList);
// read each response after they have returned
foreach (var response in responses)
{
var reader = new System.IO.StreamReader(await response.Content.ReadAsStreamAsync());
replies.Add(JsonConvert.DeserializeObject<MyData>(reader.ReadToEnd()));
reader.Close();
}
foreach (var reply in replies)
{
// do something with the response from the external api call...
}
}
Run Code Online (Sandbox Code Playgroud)
我一直得到一个TaskCanceledException.在调查之后,我看到这可能是一个超时问题.我不知道如何解决它.在尝试使用Task.WhenAll并重复之前,我试图在100个请求中批量处理我的请求.然后,当我与三组100个请求失败并行运行时.我错过了什么,有没有人对此有任何见解?
我正在尝试构建重试,HttpClient DelegatingHandler以便将诸如503 Server Unavailable和超时之类的响应视为瞬态故障并自动重试.
我从http://blog.devscrum.net/2014/05/building-a-transient-retry-handler-for-the-net-httpclient/的代码开始,该代码适用于该403 Server Unavailable案例,但不处理超时作为短暂的失败.不过,我喜欢使用Microsoft瞬态故障处理块来处理重试逻辑的一般想法.
这是我目前的代码.它使用自定义Exception子类:
public class HttpRequestExceptionWithStatus : HttpRequestException {
public HttpRequestExceptionWithStatus(string message) : base(message)
{
}
public HttpRequestExceptionWithStatus(string message, Exception inner) : base(message, inner)
{
}
public HttpStatusCode StatusCode { get; set; }
public int CurrentRetryCount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这里是瞬态故障检测器类:
public class HttpTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy {
public bool IsTransient(Exception ex)
{
var cex = ex as HttpRequestExceptionWithStatus;
var isTransient = cex != null …Run Code Online (Sandbox Code Playgroud) 我一直在使用Xamarin和MvvmCross开发一个Android应用程序,一切都很顺利,我和我的团队能够开发解决方案,本周我们决定进行最后的调整并在其他环境中测试应用程序.在测试期间,我遇到了Android解决方案的巨大问题.在工作环境中一切正常,但当我尝试在家测试应用程序时,应用程序停止工作.我检查了发生了什么,我发现HttpClient无法完成对服务器的调用并抛出以下异常:
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0
at System.Runtime.CompilerServices.TaskAwaiter`1[System.Net.Http.HttpResponseMessage].GetResult () [0x00000] in <filename unknown>:0
at System.Net.Http.HttpClientHandler+<SendAsync>c__async0.MoveNext () [0x00000] in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)
我在Google搜索了一个解决方案,我在Xamarin论坛http://forums.xamarin.com/discussion/30152/error-nameresolutionfailure(Jefimijana帖子)中发现了一个类似的问题,其中一个答案是关于网络配置错误看起来很奇怪对我来说,因为所有其他应用程序似乎工作得很好.我测试了连接到同一wifi的WPF应用程序,以检查是否有任何问题,但它工作得很好.所以我发现自己有一个更大的问题,我无法告诉用户他必须重新调整他的wifi连接,当所有其他应用程序正常工作,我不能让我的应用程序不使用某些wifis没有明显的原因.所以我的问题是,这个问题有解决方案吗?这是某种与HttpClient相关的Xamarin问题吗?或者这是一个Android问题?
谢谢,
如何使用HttpClient并动态设置方法,而不必执行以下操作:
public async Task<HttpResponseMessage> DoRequest(string url, HttpContent content, string method)
{
HttpResponseMessage response;
using (var client = new HttpClient())
{
switch (method.ToUpper())
{
case "POST":
response = await client.PostAsync(url, content);
break;
case "GET":
response = await client.GetAsync(url);
break;
default:
response = null;
// Unsupported method exception etc.
break;
}
}
return response;
}
Run Code Online (Sandbox Code Playgroud)
目前它看起来你将不得不使用:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
Run Code Online (Sandbox Code Playgroud) 我有一个ASP.NET MVC 5网站-使用C#客户端代码,我可以使用HttpClient.PutAsJsonAsync(path,myObject)很好地调用Json API(该API也是在Web API中创建的)。
client.BaseAddress = new Uri("http://mydomain");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PutAsJsonAsync("api/something", myObj);
Run Code Online (Sandbox Code Playgroud)
我想对Delete动词做同样的事情。但是client.DeleteAsync,不允许在体内传递对象。(我想在URI中记录删除原因以及要删除的项目的ID)。
有没有办法做到这一点?
asp.net-web-api dotnet-httpclient asp.net-mvc-5 asp.net-web-api2
c# ×8
.net-core ×2
polly ×2
retry-logic ×2
.net ×1
.net-4.5 ×1
android ×1
asp.net ×1
async-await ×1
asynchronous ×1
http ×1
mvvmcross ×1
webrequest ×1
xamarin ×1