Моя цель - повторить асинхронный запрос HttpWebRequest в случае сбоя.
Когда я Прервать () HttpWebRequest, я не могу снова BeginGetResponse (). Таким образом, единственный способ запросить еще раз - это воссоздать объект HttpWebRequest. Похоже, это потребует много работы, так как мне пришлось бы скопировать все свойства из старого объекта. Есть какой-нибудь ярлык?
Примечание: я думаю, что сериализация решит мою проблему, но этот класс не будет сериализован, как описано в предыдущий вопрос.
Обновлять Удален пример исходного кода, потому что он не нужен
Текущее мнение по этому поводу Нет ярлыка, единственный способ повторить запрос - это создать другой объект HttpWebRequest таким же образом, как вы создали исходный.





Где вы пытаетесь сериализовать запрос? Было бы неплохо сериализовать запрос перед, который вы пытаетесь сделать, а затем повторно отправить запрос в случае сбоя (из сериализованного экземпляра).
Кроме того, вы можете удалить прокси, сериализовать экземпляр, а затем вернуть прокси, поскольку, похоже, проблема заключается в сериализации запроса.
удалил образец кода сериализации и заменил его ссылкой на другой вопрос SO о сериализации HttpWebRequest (stackoverflow.com/questions/351265/…)
Здесь нет ярлыка, единственный способ повторить запрос - создать другой объект HttpWebRequest таким же образом, как вы создали исходный.
Это невозможно.
Экземпляр HTTPWebRequest представляет буквально один экземпляр запроса (хотя есть крайние случаи, когда он будет повторять внутреннюю попытку), и, следовательно, не является чем-то, что можно логически повторить. Он способен возвращать ровно один ответ (запрос / ответ представляет собой логическую пару), и хотя вы можете проверять этот ответ несколько раз, вы получите точно такой же объект.
По сути, вы думаете, что экземпляр HTTPWebRequest - это своего рода фабрика, но на самом деле он конкретен. Вам нужно создать еще один экземпляр.
Есть способ, посмотрите мой ответ.
Вам просто нужно создать новый HttpWebRequest и скопировать на него все свойства из старого объекта через отражение.
Вот метод расширения, который делает это:
/// <summary>
/// Clones a HttpWebRequest for retrying a failed HTTP request.
/// </summary>
/// <param name = "original"></param>
/// <returns></returns>
public static HttpWebRequest Clone(this HttpWebRequest original)
{
// Create a new web request object
HttpWebRequest clone = (HttpWebRequest)WebRequest.Create(original.RequestUri.AbsoluteUri);
// Get original fields
PropertyInfo[] properties = original.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// There are some properties that we can't set manually for the new object, for various reasons
List<string> excludedProperties = new List<String>(){ "ContentLength", "Headers" };
// Traverse properties in HttpWebRequest class
foreach (PropertyInfo property in properties)
{
// Make sure it's not an excluded property
if (!excludedProperties.Contains(property.Name))
{
// Get original field value
object value = property.GetValue(original);
// Copy the value to the new cloned object
if (property.CanWrite)
{
property.SetValue(clone, value);
}
}
}
return clone;
}
Если вы хотите повторно отправить тот же запрос, просто выполните следующее:
// Create a request
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://www.google.com/");
// Change some properties...
// Execute it
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Clone the request to reissue it using our extension method
request = request.Clone();
// Execute it again
response = (HttpWebResponse)request.GetResponse();
Блестяще. Спасибо.
Отличная идея! Но я не уверен, какие заголовки вы бы хотели скопировать нет. Например, если у вас есть информация для авторизации, вам нужно будет скопировать заголовки (по крайней мере, некоторые из них) для следующей успешной попытки.
Метод расширения не копирует заголовки, поскольку C# выдает исключение при попытке записать полные заголовки в это свойство. Вам нужно будет настроить код, чтобы читать каждый отдельный заголовок как пару «ключ-значение» и записывать его в новый клонированный объект, по одному заголовку за раз.
Полный код не содержит сериализации, потому что это не сработало, но если я включу сериализацию в код, я обязательно сделаю так, как вы сказали. В фрагменте кода, который я написал для тестов сериализации, нет ни одной строчки о прокси, и я не знаю, как его удалить. Ты?