Wenn ein Webserver auf HttpWebRequest.GetResponse()
mit HTTP 304 reagiert (nicht geändert), GetResponse()
thows eine WebException
, die für mich so sehr seltsam ist. Ist das Absicht oder vermisse ich hier etwas Offensichtliches?HttpWebRequest.GetResponse wirft WebException auf HTTP 304
Antwort
Ok, das scheint ein By-Design-Verhalten und ein perfektes Beispiel für eine vexing exception. Dies kann mit dieser gelöst werden:
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;
}
}
Das ist wirklich ein frustrierendes Problem, und kann alternativ um unter Verwendung der folgenden Erweiterungsmethode Klasse und ruft 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;
}
}
}
}
Sie gearbeitet werden gelesen mehr darüber in meinem Blog-Post zu diesem Thema bei http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/
Die Art und Weise dieses System.WebException
ist zu vermeiden AllowAutoRedirect Eigenschaft auf false
einzustellen. Dies deaktiviert die automatische Umleitungslogik des WebRequest
. Es scheint für 304 Redirection-Anfragen defekt zu sein, da es sich nicht um eine echte Umleitung im engeren Sinne handelt. Das bedeutet natürlich, dass die anderen Umleitungsanforderungen 3xx
manuell bearbeitet werden müssen.
Absolut brillant. Warum sollte ich für die schwerfällige Ausnahmemaschinerie bezahlen, wenn ich sie nicht brauche? – jsuddsjr
Ich kam auch in dieser Frage mit dem Code:
try
{
...
var webResponse = req.GetResponse();
...
}
catch (WebException ex)
{
Log.Error("Unknown error occured", ex);
//throw;
}
Und es scheint, dass, wenn der Remoteserver-304-Status zurückkehrt muss es durch das Werfen dieser Fehler oder Rückkehr benutzerdefinierten 304 so der Browser zu Browser weitergegeben werden konnte zurückkehren Cache-Antwort. Andernfalls erhalten Sie wahrscheinlich eine leere Antwort vom Remote-Server.
Also in meinem Fall für ein normales Verhalten mit der richtigen Cache sollte Umgang es sein:
try
{
...
var webResponse = req.GetResponse();
...
}
catch (WebException ex)
{
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotModified)
throw;
Log.Error("Unknown error occured", ex);
}
Nur als FYI, dies ist ein Update für Anton Gogolev's answer, die die C# 6 (VS2015) when
Klausel verwendet. Es ist ein wenig weniger ärgerlich, wenn ein Debugger wie es ein Catchpoint entfernt:
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;
}
}
Dies funktioniert meisten Fällen, aber einige Web-Server könnte eine Antwort Körper zurück, wenn ein 404-Fehler zurück. In diesem Fall würde der obige Code ein 404 behandeln, wie es ein 304 behandelt! – comshak
@comshak das ist ein "gut zu wissen." Der aufrufende Code muss sich dessen bewusst sein, was akzeptable Antwortcodes sind. – roufamatic
Ich habe auch '|| hinzugefügt ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –