使用.NET 4.5和C#中的HttpClient进行HTTP HEAD请求

The*_*gth 48 .net c# httprequest .net-4.5

是否可以使用HttpClient.NET 4.5中的新创建HTTP HEAD请求?唯一的方法我能看到的是GetAsync,DeleteAsync,PutAsyncPostAsync.我知道HttpWebRequest-class能够做到这一点,但我想使用现代HttpClient.

Smi*_*igs 79

将该SendAsync方法与使用的HttpRequestMessage构造实例一起使用HttpMethod.Head.

GetAsync,PostAsync等是方便的包装周围SendAsync; 不太常见的HTTP方法,如HEAD,OPTIONS等,没有得到的包装.


rot*_*d86 9

您也可以执行以下操作以仅获取标头:

this.GetAsync($"http://url.com", HttpCompletionOption.ResponseHeadersRead).Result;
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的优点在于,即使目标服务器明确禁止“ HEAD”请求**(例如Amazon AWS),它也可以工作。 (5认同)
  • 从代码的角度来看,我喜欢这个选项,Ian 的评论也是一个优点。但我实现了这个,Smigs 的答案和 Smigs 的答案执行得相当快......当然,我的 URL 指向 30-100MB 文件,这可能与此有关。但这个答案发出的是 GET 请求而不是 HEAD,所以请记住这一点。 (5认同)

Shi*_*iva 5

我需要这样做,以获取TotalCount我从Web API的GET方法返回的ATM .

当我尝试@ Smig的回答时,我从Web API获得了以下响应.

MethodNotAllowed:Pragma:no-cache X-SourceFiles:=?UTF-8?B?dfdsf Cache-Control:no-cache Date:Wed,22 Mar 2017 20:42:57 GMT Server:Microsoft-IIS/10.0 X-AspNet -Version:4.0.30319 X-Powered-By:ASP.NET

不得不建立在@ Smig的答案上,让它成功运作.我发现Web API方法需要Http HEAD通过在Action方法中将其指定为Attribute 来显式允许该动词.

这是完整的代码,通过代码注释进行内联解释.我删除了敏感代码.

在我的Web客户端中:

        HttpClient client = new HttpClient();

        // set the base host address for the Api (comes from Web.Config)
        client.BaseAddress = new Uri(ConfigurationManager.AppSettings.Get("ApiBase"));
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add( 
          new MediaTypeWithQualityHeaderValue("application/json"));

        // Construct the HEAD only needed request. Note that I am requesting
        //  only the 1st page and 1st record from my API's endpoint.
        HttpRequestMessage request = new HttpRequestMessage(
          HttpMethod.Head, 
          "api/atms?page=1&pagesize=1");

        HttpResponseMessage response = await client.SendAsync(request);

        // FindAndParsePagingInfo is a simple helper I wrote that parses the 
        // json in the Header and populates a PagingInfo poco that contains 
        // paging info like CurrentPage, TotalPages, and TotalCount, which 
        // is the total number of records in the ATMs table.
        // The source code is pasted separately in this answer.
        var pagingInfoForAtms = HeaderParser.FindAndParsePagingInfo(response.Headers);

        if (response.IsSuccessStatusCode)
            // This for testing only. pagingInfoForAtms.TotalCount correctly
            //  contained the record count
            return Content($"# of ATMs {pagingInfoForAtms.TotalCount}");

            // if request failed, execution will come through to this line 
            // and display the response status code and message. This is how
            //  I found out that I had to specify the HttpHead attribute.
            return Content($"{response.StatusCode} : {response.Headers.ToString()}");
        }
Run Code Online (Sandbox Code Playgroud)

在Web API中.

    // Specify the HttpHead attribute to avoid getting the MethodNotAllowed error.
    [HttpGet, HttpHead]
    [Route("Atms", Name = "AtmsList")]
    public IHttpActionResult Get(string sort="id", int page = 1, int pageSize = 5)
    {
        try
        {
            // get data from repository
            var atms =  _atmRepository.GetAll().AsQueryable().ApplySort(sort);
            // ... do some code to construct pagingInfo etc.
            // .......
            // set paging info in header.
            HttpContext.Current.Response.Headers.Add(
              "X-Pagination", JsonConvert.SerializeObject(paginationHeader));
            // ...
            return Ok(pagedAtms));
        }
        catch (Exception exception)
        {
            //... log and return 500 error
        }
    }
Run Code Online (Sandbox Code Playgroud)

FindAndParsePagingInfo用于解析分页标头数据的Helper方法.

public static class HeaderParser
{
public static PagingInfo FindAndParsePagingInfo(HttpResponseHeaders responseHeaders)
{
    // find the "X-Pagination" info in header
    if (responseHeaders.Contains("X-Pagination"))
    {
        var xPag = responseHeaders.First(ph => ph.Key == "X-Pagination").Value;

        // parse the value - this is a JSON-string.
        return JsonConvert.DeserializeObject<PagingInfo>(xPag.First());
    }

    return null;
}

public static string GetSingleHeaderValue(HttpResponseHeaders responseHeaders, 
    string keyName)
{
    if (responseHeaders.Contains(keyName))
        return responseHeaders.First(ph => ph.Key == keyName).Value.First();

    return null;
}
Run Code Online (Sandbox Code Playgroud)

}