Si necesita una respuesta breve y técnica, vaya directamente a la última sección de la respuesta.
Si quieres saber mejor, léelo todo, y espero que disfrutes ...
También he contrarrestado este problema hoy, y lo que descubrí hoy es que:
Las respuestas anteriores son verdaderas, como:
1.1 le dice que el encabezado que está tratando de agregar ya existe y que debe modificar su valor utilizando la propiedad apropiada (el indexador, por ejemplo), en lugar de intentar agregarlo nuevamente.
1.2 Cada vez que cambie los encabezados de un HttpWebRequest
, debe usar las propiedades apropiadas en el objeto, si existen.
Gracias por y Jvenema por las pautas principales ...
Pero, lo que descubrí, y esa fue la pieza que faltaba en el rompecabezas es que:
2.1 WebHeaderCollection
Generalmente se accede a la clase a través de WebRequest
.Headers o WebResponse
.Headers. Algunos encabezados comunes se consideran restringidos y están expuestos directamente por la API (como Content-Type) o protegidos por el sistema y no se pueden cambiar.
Los encabezados restringidos son:
Accept
Connection
Content-Length
Content-Type
Date
Expect
Host
If-Modified-Since
Range
Referer
Transfer-Encoding
User-Agent
Proxy-Connection
Entonces, la próxima vez que se enfrente a esta excepción y no sepa cómo resolver esto, recuerde que hay algunos encabezados restringidos, y la solución es modificar sus valores usando la propiedad apropiada explícitamente de la clase WebRequest
/ HttpWebRequest
.
Editar: (útil, de los comentarios, comentario del usuario Kaido )
La solución es verificar si el encabezado ya existe o está restringido ( WebHeaderCollection.IsRestricted(key)
) antes de llamar a agregar
Headers.Add()
ya existe, por lo tanto, deberíamos modificarla.Me encontré con este problema con un cliente web personalizado. Creo que las personas pueden estar confundidas debido a múltiples formas de hacer esto. Cuando lo use
WebRequest.Create()
, puede emitirHttpWebRequest
y usar la propiedad para agregar o modificar un encabezado. Cuando use unWebHeaderCollection
puede usar el.Add("referer","my_url")
.Ex 1
Ex 2
fuente
Todas las respuestas anteriores describen el problema sin proporcionar una solución. Aquí hay un método de extensión que resuelve el problema al permitirle configurar cualquier encabezado a través de su nombre de cadena.
Uso
Clase de extensión
Escenarios
Escribí un contenedor para
HttpWebRequest
y no quería exponer los 13 encabezados restringidos como propiedades en mi contenedor. En cambio, quería usar un simpleDictionary<string, string>
.Otro ejemplo es un proxy HTTP donde necesita tomar encabezados en una solicitud y reenviarlos al destinatario.
Hay muchos otros escenarios en los que no es práctico ni posible usar propiedades. Forzar al usuario a establecer el encabezado a través de una propiedad es un diseño muy inflexible, por lo que se necesita reflexión. Lo bueno es que el reflejo se abstrae, sigue siendo rápido (0,001 segundo en mis pruebas) y, como método de extensión, se siente natural.
Notas
Los nombres de encabezado no distinguen entre mayúsculas y minúsculas según RFC, http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
fuente
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); } } }
Tuve la misma excepción cuando mi código intentó establecer el valor del encabezado "Aceptar" de esta manera:
La solución fue cambiarlo a esto:
fuente
Cada vez que cambie los encabezados de un
HttpWebRequest
, debe usar las propiedades apropiadas en el objeto, si existen. Si tienes un llanoWebRequest
, asegúrate de lanzarlo porHttpWebRequest
primera vez. Luego,Referrer
en su caso, se puede acceder a través de((HttpWebRequest)request).Referrer
, por lo que no necesita modificar el encabezado directamente, solo configure la propiedad en el valor correcto.ContentLength
,ContentType
,UserAgent
, Etc, todo es necesario establecer de esta manera.En mi humilde opinión, esta es una deficiencia en la parte de MS ... configurar los encabezados a través de
Headers.Add()
debería llamar automáticamente a la propiedad apropiada detrás de escena, si eso es lo que quieren hacer.fuente
WebRequest es abstracto (y dado que cualquier clase debe anular la propiedad Headers) ... ¿qué WebRequest concreta está utilizando? En otras palabras, ¿cómo se consigue que ese objeto WebRequest se alinee?
ehr ... nuestra respuesta me hizo darme cuenta de que el mensaje de error que estaba recibiendo es acertado: le dice que el encabezado que está intentando agregar ya existe y que debe modificar su valor utilizando la propiedad apropiada (el indexador, por ejemplo ), en lugar de intentar agregarlo nuevamente. Eso es probablemente todo lo que estabas buscando.
Otras clases que heredan de WebRequest pueden tener propiedades aún mejores que envuelven ciertos encabezados; Ver esta publicación, por ejemplo.
fuente
Las respuestas anteriores están bien, pero la esencia del problema es que algunos encabezados se configuran de una manera, y otros se configuran de otra manera. Ver arriba para las listas de 'encabezado restringido'. Para estos, simplemente los configura como una propiedad. Para otros, en realidad agrega el encabezado. Mira aquí.
fuente
Básicamente no. Ese es un encabezado http, por lo que es razonable enviar
HttpWebRequest
y configurar el.Referer
(como indica en la pregunta):fuente
Nota: esta solución funcionará con WebClientSocket, así como con HttpWebRequest o cualquier otra clase que use WebHeaderCollection para trabajar con encabezados.
Si observa el código fuente de WebHeaderCollection.cs, verá que Hinfo se utiliza para mantener información de todos los encabezados conocidos:
Al observar la clase HeaderInfoTable, puede observar que todos los datos se almacenan en la tabla hash
Además, en el constructor estático de HeaderInfoTable, puede ver que todos los encabezados conocidos se agregan en la matriz HeaderInfo y luego se copian en la tabla hash.
La última mirada a la clase HeaderInfo muestra los nombres de los campos.
Entonces, con todo lo anterior, aquí hay un código que usa la reflexión para encontrar Hashtable estático en la clase HeaderInfoTable y luego cambia cada tabla de hash dentro de la tabla hash restringida por solicitud para que no esté restringida
fuente
Estoy usando solo:
fuente
Puede enviar WebRequest a una HttpWebRequest que se muestra a continuación:
y luego, en lugar de tratar de manipular la lista de encabezados, aplíquela directamente en la solicitud de propiedad de solicitud.
Estas propiedades están disponibles en el objeto de solicitud.
fuente