Когда веб-сервер отвечает на HttpWebRequest.GetResponse()
HTTP 304 (не изменено), GetResponse()
выдает WebException
, что для меня очень странно. Это по дизайну или я упустил что-то очевидное здесь?
HttpWebRequest.GetResponse выдает WebException на HTTP 304
Ответы (5)
Хорошо, похоже, это поведение по дизайну и прекрасный пример досадное исключение. Это можно решить с помощью этого:
public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
try
{
return (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
{
if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
throw;
return (HttpWebResponse)ex.Response;
}
}
|| ((HttpWebResponse) ex.Response).StatusCode != HttpStatusCode.NotModified
- person Danny Beckett; 25.11.2013
when
C#-6.0!
- person binki; 06.01.2016
Это действительно неприятная проблема, и в качестве альтернативы ее можно обойти, используя следующий класс метода расширения и вызвав request.BetterGetResponse().
//-----------------------------------------------------------------------
//
// Copyright (c) 2011 Garrett Serack. All rights reserved.
//
//
// The software is licensed under the Apache 2.0 License (the "License")
// You may not use the software except in compliance with the License.
//
//-----------------------------------------------------------------------
namespace CoApp.Toolkit.Extensions {
using System;
using System.Net;
public static class WebRequestExtensions {
public static WebResponse BetterEndGetResponse(this WebRequest request, IAsyncResult asyncResult) {
try {
return request.EndGetResponse(asyncResult);
}
catch (WebException wex) {
if( wex.Response != null ) {
return wex.Response;
}
throw;
}
}
public static WebResponse BetterGetResponse(this WebRequest request) {
try {
return request.GetResponse();
}
catch (WebException wex) {
if( wex.Response != null ) {
return wex.Response;
}
throw;
}
}
}
}
Подробнее об этом читайте в моем блоге на эту тему по адресу http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-статус/
Чтобы избежать этого System.WebException
, нужно установить AllowAutoRedirect на false
. Это отключает логику автоматического перенаправления файла WebRequest
. Кажется, он сломан для 304 запросов перенаправления, так как это не настоящее перенаправление в самом строгом смысле. Конечно, это означает, что другие запросы перенаправления 3xx
должны обрабатываться вручную.
Как и для вашего сведения, это обновление ответа Антона Гоголева, в котором используется предложение C#6 (VS2015) when
. Это немного менее раздражает при использовании отладчика, поскольку он удаляет одну точку перехвата:
public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
try
{
return (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
when (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
{
return (HttpWebResponse) ex.Response;
}
}
Я также столкнулся с этой проблемой с кодом:
try
{
...
var webResponse = req.GetResponse();
...
}
catch (WebException ex)
{
Log.Error("Unknown error occured", ex);
//throw;
}
И похоже, что если удаленный сервер возвращает статус 304, его необходимо передать в браузер, выдав эту ошибку или вернув пользовательский 304, чтобы браузер мог вернуть кешированный ответ. В противном случае вы, вероятно, получите пустой ответ от удаленного сервера.
Итак, в моем случае для нормального поведения с правильной обработкой кеша это должно быть так:
try
{
...
var webResponse = req.GetResponse();
...
}
catch (WebException ex)
{
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotModified)
throw;
Log.Error("Unknown error occured", ex);
}