Wenn Sie eine kurze und technische Antwort benötigen, fahren Sie mit dem letzten Abschnitt der Antwort fort.
Wenn Sie es besser wissen wollen, lesen Sie alles und ich hoffe, Sie werden es genießen ...
Ich habe diesem Problem auch heute begegnet, und was ich heute entdeckt habe, ist Folgendes:
Die obigen Antworten sind wahr als:
1.1 Es sagt Ihnen, dass der Header, den Sie hinzufügen möchten, bereits vorhanden ist, und Sie sollten seinen Wert dann mithilfe der entsprechenden Eigenschaft (z. B. des Indexers) ändern, anstatt erneut zu versuchen, ihn hinzuzufügen.
1.2 Jedes Mal HttpWebRequest
, wenn Sie die Header von ändern , müssen Sie die entsprechenden Eigenschaften für das Objekt selbst verwenden, falls vorhanden.
Vielen Dank für und Jvenema für die führenden Richtlinien ...
Aber was ich herausgefunden habe und das war das fehlende Teil im Puzzle ist:
2.1 Auf die WebHeaderCollection
Klasse wird im Allgemeinen über WebRequest
.Headers oder WebResponse
.Headers zugegriffen. Einige häufig verwendete Header gelten als eingeschränkt und werden entweder direkt von der API (z. B. Content-Type) verfügbar gemacht oder vom System geschützt und können nicht geändert werden.
Die eingeschränkten Header sind:
Accept
Connection
Content-Length
Content-Type
Date
Expect
Host
If-Modified-Since
Range
Referer
Transfer-Encoding
User-Agent
Proxy-Connection
Wenn Sie das nächste Mal mit dieser Ausnahme konfrontiert sind und nicht wissen, wie Sie sie lösen sollen, denken Sie daran, dass es einige eingeschränkte Header gibt. Die Lösung besteht darin, ihre Werte mithilfe der entsprechenden Eigenschaft explizit aus der Klasse WebRequest
/ zu ändern HttpWebRequest
.
Bearbeiten: (nützlich, aus Kommentaren, Kommentar von Benutzer Kaido )
Die Lösung besteht darin, WebHeaderCollection.IsRestricted(key)
vor dem Aufruf von add zu überprüfen, ob der Header bereits vorhanden oder eingeschränkt ist ( )
Headers.Add()
bereits vorhanden ist. Daher sollten wir sie stattdessen ändern.Ich bin auf dieses Problem mit einem benutzerdefinierten Webclient gestoßen. Ich denke, die Leute könnten verwirrt sein, weil es mehrere Möglichkeiten gibt, dies zu tun. Bei Verwendung können
WebRequest.Create()
SieHttpWebRequest
einen Header umwandeln und mithilfe der Eigenschaft einen Header hinzufügen oder ändern. WennWebHeaderCollection
Sie ein verwenden , können Sie das verwenden.Add("referer","my_url")
.Ex 1
Ex 2
quelle
Alle vorherigen Antworten beschreiben das Problem, ohne eine Lösung bereitzustellen. Hier ist eine Erweiterungsmethode, die das Problem löst, indem Sie einen beliebigen Header über seinen Zeichenfolgennamen festlegen können.
Verwendung
Erweiterungsklasse
Szenarien
Ich habe einen Wrapper für geschrieben
HttpWebRequest
und wollte nicht alle 13 eingeschränkten Header als Eigenschaften in meinem Wrapper verfügbar machen. Stattdessen wollte ich eine einfache verwendenDictionary<string, string>
.Ein weiteres Beispiel ist ein HTTP-Proxy, bei dem Sie Header in einer Anforderung aufnehmen und an den Empfänger weiterleiten müssen.
Es gibt viele andere Szenarien, in denen es einfach nicht praktikabel oder möglich ist, Eigenschaften zu verwenden. Den Benutzer zu zwingen, den Header über eine Eigenschaft zu setzen, ist ein sehr unflexibles Design, weshalb Reflexion erforderlich ist. Der Vorteil ist, dass die Reflexion weg abstrahiert wird, immer noch schnell ist (0,001 Sekunden in meinen Tests) und sich als Erweiterungsmethode natürlich anfühlt.
Anmerkungen
Bei Headernamen wird gemäß RFC ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) die Groß- und Kleinschreibung nicht berücksichtigt
quelle
static Dictionary<string, PropertyInfo> HeaderProperties = new Dictionary<string, PropertyInfo>(StringComparer.InvariantCultureIgnoreCase); static WebRequestExtensions() { // Get property info for restricted headers. Type type = typeof(HttpWebRequest); foreach (string header in Enum.GetNames(typeof(HttpRequestHeader))) { var property = type.GetProperty(header.ToString()); if (property != null) { HeaderProperties.Add(property.Name, property); } } }
Ich hatte die gleiche Ausnahme, als mein Code versuchte, den Header-Wert "Accept" wie folgt festzulegen:
Die Lösung bestand darin, dies zu ändern:
quelle
Jedes Mal
HttpWebRequest
, wenn Sie die Header von ändern , müssen Sie die entsprechenden Eigenschaften für das Objekt selbst verwenden, sofern diese vorhanden sind. Wenn Sie eine Ebene habenWebRequest
, stellen Sie sicher, dass Sie eineHttpWebRequest
erste verwenden. DannReferrer
in Ihrem Fall kann abgerufen werden((HttpWebRequest)request).Referrer
, so dass Sie nicht den Header müssen direkt ändern - nur die Eigenschaft auf den richtigen Wert gesetzt.ContentLength
,ContentType
,UserAgent
, Usw, alle müssen auf diese Weise eingestellt werden.IMHO, dies ist ein Mangel für MS-Teil ... das Setzen der Header über
Headers.Add()
sollte automatisch die entsprechende Eigenschaft hinter den Kulissen aufrufen, wenn sie dies tun möchten.quelle
WebRequest ist abstrakt (und da jede erbende Klasse die Headers-Eigenschaft überschreiben muss). Welche konkrete WebRequest verwenden Sie? Mit anderen Worten, wie erhalten Sie das WebRequest-Objekt, mit dem Sie übereinstimmen?
ehr .. mnour Antwort hat mir klar gemacht, dass die Fehlermeldung, die Sie erhalten haben, genau richtig ist: Sie sagt Ihnen, dass der Header, den Sie hinzufügen möchten, bereits vorhanden ist, und Sie sollten seinen Wert dann mithilfe der entsprechenden Eigenschaft (z. B. des Indexers) ändern ), anstatt zu versuchen, es erneut hinzuzufügen. Das ist wahrscheinlich alles, wonach Sie gesucht haben.
Andere Klassen, die von WebRequest erben, haben möglicherweise noch bessere Eigenschaften, die bestimmte Header umschließen. Siehe diesen Beitrag zum Beispiel.
quelle
Die obigen Antworten sind alle in Ordnung, aber das Wesentliche des Problems ist, dass einige Header in eine Richtung und andere in eine andere Richtung gesetzt werden. Siehe oben für 'eingeschränkte Header'-Listen. Für diese legen Sie sie einfach als Eigenschaft fest. Für andere fügen Sie tatsächlich die Kopfzeile hinzu. Siehe hier.
quelle
Grundsätzlich nein. Da es sich um einen http-Header handelt, ist es sinnvoll, Folgendes zu ändern
HttpWebRequest
und festzulegen.Referer
(wie Sie in der Frage angeben):quelle
Hinweis: Diese Lösung funktioniert sowohl mit WebClientSocket als auch mit HttpWebRequest oder einer anderen Klasse, die WebHeaderCollection verwendet, um mit Headern zu arbeiten.
Wenn Sie sich den Quellcode von WebHeaderCollection.cs ansehen, werden Sie feststellen, dass Hinfo verwendet wird, um Informationen zu allen bekannten Headern zu speichern:
Wenn Sie sich die HeaderInfoTable-Klasse ansehen, können Sie feststellen, dass alle Daten in einer Hash-Tabelle gespeichert sind
Außerdem können Sie im statischen Konstruktor von HeaderInfoTable sehen, dass alle bekannten Header im HeaderInfo-Array hinzugefügt und dann in die Hashtabelle kopiert werden.
Der letzte Blick auf die HeaderInfo-Klasse zeigt die Namen der Felder.
Bei all dem ist hier ein Code, der mithilfe von Reflektion statische Hashtable in der HeaderInfoTable-Klasse findet und dann jede anforderungsbeschränkte HeaderInfo in der Hash-Tabelle so ändert, dass sie nicht eingeschränkt wird
quelle
Ich benutze nur:
quelle
Sie können die WebRequest einfach in eine unten gezeigte HttpWebRequest umwandeln:
und anstatt zu versuchen, die Header-Liste zu manipulieren, wenden Sie sie direkt in der Anfrage-Eigenschaftsanforderung an. Referenz:
Diese Eigenschaften sind im Anforderungsobjekt verfügbar.
quelle