Как правильно использовать HttpClient в .NET 4.6.1 + ASP.NET Web API 2C#

Место общения программистов C#
Ответить
Anonymous
 Как правильно использовать HttpClient в .NET 4.6.1 + ASP.NET Web API 2

Сообщение Anonymous »

Я создаю эту статью с помощью машинного перевода. Простите за грамматические ошибки.
Я поддерживаю веб-API ASP.NET 2, работающий на .NET 4.6.1.
(Не упоминайте об окончании поддержки! Я много раз говорил им, чтобы они обновились. Горе моему несимпатичному боссу!!)
В этом приложении я думаю. использования HttpClient для доступа к другим веб-серверам.
Вот код, который я написал:
namespace myApps.Controllers.WebAPI
{
public class TempTestController : ApiController
{
private static HttpClient httpClient = new HttpClient();

[Route("AthorSiteContent")]
public IHttpActionResult getAthorSiteContent(string A_few_URLs)
{
var firstRequest = new System.Net.Http.HttpRequestMessage();
firstRequest.Method = System.Net.Http.HttpMethod.Head;
firstRequest.RequestUri = new Uri(A_few_URLs);

var firstResponse = httpClient.SendAsync(firstRequest).GetAwaiter().GetResult();

// check headers(host, status, Content-Type, Content-Length, etc...)
// If the content cannot be downloaded, the process ends here.

var secondRequest = new System.Net.Http.HttpRequestMessage();
secondRequest.Method = System.Net.Http.HttpMethod.Get;
secondRequest.RequestUri = new Uri(A_few_URLs);

var secondResponse = httpClient.SendAsync(secondRequest).GetAwaiter().GetResult();

var contentData = secondResponse.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();

// Save contentData to a file

return new ResponseMessageResult(this.Request.CreateResponse(HttpStatusCode.NoContent));
}
}
}

Безопасен ли этот код? Не приведет ли это к исчерпанию сокетов?
Кроме того, я не использую HttpWebRequest, поскольку нашел информацию, которая

использование HttpWebRequest в ASP.NET может привести к исчерпанию сокетов.

обновление:
На основании полученного совета я изменил исходный код, добавив следующие функции:
  • Удаление ненужных экземпляров и поддержка DNS обновления
  • Используйте разные экземпляры HttpClient для каждого хоста
PS: Спасибо Neil T за то, что сообщил мне, что машинный перевод был верным! :-)
public class TempTestController : ApiController
{
//for multithreading
private static ConcurrentDictionary httpClientDics = new ConcurrentDictionary();

[Route("AthorSiteContent")]
public async Task getAthorSiteContent(string A_few_URLs)
{
//To delete unnecessary instances and deal with DNS updates.
var httpClientDicsKeys = new List(httpClientDics.Keys);
foreach (var key in httpClientDicsKeys)
{
if (httpClientDics[key].lastAccess < DateTime.Now.AddMinutes(-60))
{
httpClientDics[key].Dispose();
httpClientDics.TryRemove(key, out httpClientWrapper removeObject);
}
}

//Create an instance of HttpClient required to access BaseAddress if it does not already exist.
string baseAddress = httpClientWrapper.getBaseAddressFromURL(A_few_URLs);
if (!httpClientDicsKeys.Contains(baseAddress))
{
httpClientDics.TryAdd(baseAddress, new httpClientWrapper(A_few_URLs));
}

{
var firstRequest = new System.Net.Http.HttpRequestMessage();
firstRequest.Method = System.Net.Http.HttpMethod.Head;
firstRequest.RequestUri = new Uri(A_few_URLs);
var firstResponse = await httpClientDics[baseAddress].httpClient.SendAsync(firstRequest);

//check headers(host, status, Content-Type, Content-Length, etc...)
//If the content cannot be downloaded, the process ends here.
}

//If site cannot be accessed because DNS has been updated, lastAccess will not be changed.
httpClientDics[baseAddress].lastAccess = DateTime.Now;

{
var secondRequest = new System.Net.Http.HttpRequestMessage();
secondRequest.Method = System.Net.Http.HttpMethod.Get;
secondRequest.RequestUri = new Uri(A_few_URLs);
var secondResponse = await httpClientDics[baseAddress].httpClient.SendAsync(secondRequest);
var contentData = await secondResponse.Content.ReadAsByteArrayAsync();

//Save contentData to a file
}

return new ResponseMessageResult(this.Request.CreateResponse(HttpStatusCode.NoContent));
}
}

class httpClientWrapper : IDisposable
{
public HttpClient httpClient { get; set; }
public DateTime lastAccess { get; set; } = DateTime.Now;
public httpClientWrapper(string url)
{
this.httpClient = new HttpClient()
{
BaseAddress = new Uri(httpClientWrapper.getBaseAddressFromURL(url))
};
}

public static string getBaseAddressFromURL(string url)
{
var uri = new Uri(url);
return uri.GetLeftPart(UriPartial.Authority);
}

//Microsoft, this code is not COOL...
#region IDisposable Support
private bool disposedValue = false;

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
this.httpClient.Dispose();
}
this.httpClient = null;
disposedValue = true;
}
}

~httpClientWrapper()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
}
#endregion
}


Подробнее здесь: https://stackoverflow.com/questions/786 ... -web-api-2
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»