Error while copying content to a stream
Я использую класс HttpClient в .NET Framework 4.5.2.
Я вызываю PostAsync для сторонней веб-службы. в 80% случаев этот пост работает, в 20% случаев наш ответ прерывается. В этой ситуации мы получаем следующее исключение:
System.Net.Http.HttpRequestException: Error while copying content to a stream. –
Последующий идентичный запрос выполняется успешно.
Мы не можем повторить этот запрос, поскольку бизнес-действие уже выполнено. Таким образом, это ставит нас в неловкое положение.
Это мой код:
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = authorizationHeader;
HttpContent httpContent = new StringContent(someXml);
//Exception occurs on next line…
var response = await httpClient.PostAsync(“https://thirdpartyendpoint”, httpContent);
var responseXml = await response.Content.ReadAsStringAsync();
//convert to Dto
}
Сторонняя служба успешно сохраняет запись в свою базу данных и не видит никаких очевидных исключений в их конце. Они отметили, что неудачные запросы обычно занимали больше времени (около 18-30 секунд) для записи в базу данных, чем успешные запросы.
Что я могу сделать, чтобы справиться с этим лучше?
Ответ
Мы решили эту проблему с помощью 2 изменений кода:
Удалите HttpResponseMessage и просто работайте с простым DTO
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
{
return await CreateDto(httpResponseMessage);
}
Понизьте версию HTTP до версии v1.0
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(url))
{
Version = HttpVersion.Version10,
Content = httpContent
};
await client.SendAsync(httpRequestMessage);
что приводит к добавлению этого заголовка Http
Connection: close
вместо этого
Connection: keep-alive
Это мой код:
ServerURL = GetServerUri(ServerURL);
HttpContent content = new StringContent(данные.toString(), кодирование.UTF8, “application/json”);
Клиент HttpClient = новый HttpClient(новый HttpClientHandler() { UseDefaultCredentials = true });
клиент.BaseAddress = новый Uri(ServerURL);
содержимое.Заголовки.ContentType = new MediaTypeWithQualityHeaderValue(“application / json”);
клиент.DefaultRequestHeaders.Принять.Добавить(
new MediaTypeWithQualityHeaderValue(“application /json”));
ответ var = клиент.PostAsync(url, содержимое).Результат;
возвращает ответ.Содержание.ReadAsStringAsync().Результат;
Он отлично работает, когда я развертываю веб-api на корневом уровне. например: http:\\servername\api\controller\method
Но когда я развертываю веб-api следующим образом: http:\\servername\apiname\api\controller\method
Это вызывает это исключение.
Есть идеи?
Ответ
Вы должны определить пользовательскую маршрутизацию в своей конфигурации, пожалуйста, добавьте ниже маршрут в свой WebApiConfig ниже, например :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: “DefaultApi”,
routeTemplate: “api/{controller}/{id}”,
defaults: new { id = RouteParameter.Optional }
);
/ this is a new route
config.Routes.MapHttpRoute(
name: “DefaultApi_new”,
routeTemplate: “{apiname}/api/{controller}/{id}”,
defaults: new { id = RouteParameter.Optional }
);
}
}
теперь вы можете попробовать оба URL-адреса.