HttpClient有一个内置超时功能(尽管都是异步的,即超时可以被认为是与http请求功能正交,因此可以由通用异步实用程序处理,但是除此之外)当超时启动时,它会抛出一个TaskCanceledException(包含在内) a AggregateException).
TCE包含CancellationToken等于的CancellationToken.None.
现在,如果我提供HttpClient了CancellationToken我自己的一个并使用它来取消操作完成(或超时),我得到完全相同TaskCanceledException,再次使用CancellationToken.None.
通过仅查看抛出的异常,还有一种方法可以确定超时是否取消了请求,而不必让我自己CancellationToken可以访问检查异常的代码?
PS这可能是一个错误,并CancellationToken以某种方式错误地修复CancellationToken.None?在取消使用自定义CancellationToken的情况下,我希望TaskCanceledException.CancellationToken等于该自定义令牌.
编辑
为了使问题更加清晰,通过访问原始文件CancellationTokenSource,很容易区分超时和用户取消:
origCancellationTokenSource.IsCancellationRequested == true
CancellationToken从异常中获取但是给出了错误的答案:
((TaskCanceledException)e.InnerException).CancellationToken.IsCancellationRequested == false
这是一个最小的例子,由于受欢迎的需求:
public void foo()
{
makeRequest().ContinueWith(task =>
{
try
{
var result = task.Result;
// do something with the result;
}
catch (Exception e)
{
TaskCanceledException innerException = e.InnerException as TaskCanceledException;
bool …Run Code Online (Sandbox Code Playgroud) 我想多次发送完全相同的请求,例如:
HttpClient client = new HttpClient();
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, "http://example.com");
await client.SendAsync(req, HttpCompletionOption.ResponseContentRead);
await client.SendAsync(req, HttpCompletionOption.ResponseContentRead);
Run Code Online (Sandbox Code Playgroud)
第二次发送请求将抛出异常消息:
请求消息已发送.无法多次发送相同的请求消息.
他们是一种" 克隆 "请求的方式,以便我可以再次发送?
我的实际代码HttpRequestMessage在上面的示例中设置了更多变量,变量如header和request方法.
我想将此数据发布到Web API服务器:
public sealed class SomePostRequest
{
public int Id { get; set; }
public byte[] Content { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
将此代码用于服务器:
[Route("Incoming")]
[ValidateModel]
public async Task<IHttpActionResult> PostIncomingData(SomePostRequest requestData)
{
// POST logic here
}
Run Code Online (Sandbox Code Playgroud)
这个 - 对于客户:
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:25001/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "id", "1" },
{ "content", "123" }
});
var result = await client.PostAsync("api/SomeData/Incoming", content);
result.EnsureSuccessStatusCode();
Run Code Online (Sandbox Code Playgroud)
一切正常(至少,调试器在断点处停止PostIncomingData).
由于有一个 …
我目前正在使用几个委托处理程序(派生自的类DelegatingHandler)在发送之前处理请求,例如验证签名等.这一切都非常好,因为我不必在所有调用上复制签名验证(例如).
我想对来自同一Web请求的响应使用相同的原则.是否有类似于DelegatingHandler的响应?在某种方式中,在返回到方法之前捕获响应的方法是什么?
附加信息:我正在使用web api HttpClient.PutAsync(...)
我在.Net Framework 4.5上运行的ASP.Net MVC 4 Web Api项目中使用HttpClient调用外部服务
示例代码如下(忽略返回值,因为这是测试调用外部服务的示例代码):
public class ValuesController : ApiController
{
static string _address = "http://api.worldbank.org/countries?format=json";
private string result;
// GET api/values
public IEnumerable<string> Get()
{
GetResponse();
return new string[] { result, "value2" };
}
private async void GetResponse()
{
var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(_address);
response.EnsureSuccessStatusCode();
result = await response.Content.ReadAsStringAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
虽然私有方法中的代码确实可以解决我的问题,但是Controller Get()调用了GetResponse(),但是它没有等待结果,而是立即执行带有result = null的返回.
我也尝试过使用WebClient进行更简单的同步调用,如下所示:
// GET api/values
public IEnumerable<string> Get()
{
//GetResponse();
var client = new WebClient();
result = …Run Code Online (Sandbox Code Playgroud) 我正在开发一个C#控制台应用程序,用于测试URL是有效还是有效.它适用于大多数URL,并且可以从目标网站获得HTTP状态代码的响应.但是在测试其他一些URL时,应用程序会在运行HttpClient.SendAsync方法时抛出"发送请求时发生错误"异常.因此,即使此URL实际上在浏览器中有效,我也无法获得任何响应或HTTP状态代码.我迫不及待地想知道如何处理这个案子.如果URL不起作用或服务器拒绝我的请求,它至少应该给我相应的HTTP状态代码.
以下是我的测试应用程序的简化代码:
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace TestUrl
{
class Program
{
static void Main(string[] args)
{
// var urlTester = new UrlTester("http://www.sitename.com/wordpress"); // works well and get 404
// var urlTester = new UrlTester("http://www.fc.edu/"); // Throw exception and the URL doesn't work
var urlTester = new UrlTester("http://www.ntu.edu.tw/english/"); // Throw exception and the URL works actually
Console.WriteLine("Test is started");
Task.WhenAll(urlTester.RunTestAsync());
Console.WriteLine("Test is stoped");
Console.ReadKey();
}
public class UrlTester
{
private HttpClient _httpClient;
private string _url;
public UrlTester(string url) …Run Code Online (Sandbox Code Playgroud) 目前,我正在研究API包装器.如果我把一个坏的Consumer Key,服务器将返回Status如403 Forbidden在标题.它还将传递自定义标头.我如何实际检索这些自定义标头?
这是从服务器接收的响应.
Cache-Control: private
Date: Wed, 01 May 2013 14:36:17 GMT
P3P: policyref="/w3c/p3p.xml", CP="ALL CURa ADMa DEVa OUR IND UNI COM NAV INT STA PRE"
Server: Apache/2.2.23 (Amazon)
Status: 403 Forbidden
X-Error: Invalid consumer key.
X-Error-Code: 152
X-Powered-By: PHP/5.3.20
Connection: keep-alive
Run Code Online (Sandbox Code Playgroud)
我需要检索X-Error和X-Error-Code.目前,我正在使用HttpClient类来处理请求.如果我在VS Studio 2012的Quick Watch下观看标题响应,我可以像这样找到它
((System.Net.Http.Headers.HttpHeaders)(response.Headers)).headerStore["X-Error-Code"].ParsedValue
有没有其他方法可以做到这一点?
编辑:
headerStore无法通过代码访问,因为这是私有字段.我只能通过Quick Watch窗口访问它.
这是我的请求片段:
var response = await _httpClient.PostAsync("/v3/oauth/request", content);
Run Code Online (Sandbox Code Playgroud) 为了重用开放的TCP连接,HttpClient您必须为所有请求共享一个实例.
这意味着我们不能简单地HttpClient使用不同的设置(例如超时或标头)进行实例化.
我们如何共享连接并同时使用不同的设置?这很简单,实际上是默认的,旧的HttpWebRequest和WebClient基础设施.
请注意,HttpClient.Timeout在发出请求之前简单设置不是线程安全的,并且不能在并发应用程序(例如ASP.NET网站)中工作.
我正在尝试使用HttpClient需要基本HTTP身份验证的第三方服务.我正在使用AuthenticationHeaderValue.这是我到目前为止所提出的:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
t =>
{
return t.Result.Content.ReadAsAsync<ResponseType>();
}).Unwrap().Result;
Run Code Online (Sandbox Code Playgroud)
看起来POST动作工作正常,但我没有收到我期望的数据.通过一些试验和错误,并最终使用Fiddler来嗅探原始流量,我发现授权标头没有被发送.
我已经看过了,但我认为我已经将指定的身份验证方案指定为AuthenticationHeaderValue构造函数的一部分.
有没有我错过的东西?
我可以设置自定义用户代理HttpClient吗?
我需要以移动形式查看网站.