c# - headers - No se pueden establecer algunos encabezados HTTP al usar System.Net.WebRequest
webrequest c# (10)
Básicamente, no. Es un encabezado http, por lo que es razonable HttpWebRequest
a HttpWebRequest
y configurar el .Referer
(como lo indica en la pregunta):
HttpWebRequest req = ...
req.Referer = "your url";
Cuando trato de agregar un par de clave / valor de encabezado HTTP en un objeto WebRequest
, obtengo la siguiente excepción:
Este encabezado debe ser modificado usando la propiedad apropiada
Intenté agregar nuevos valores a la colección Headers
utilizando el método Add (), pero sigo recibiendo la misma excepción.
webRequest.Headers.Add(HttpRequestHeader.Referer, "http://stackoverflow.com");
Puedo evitar esto lanzando el objeto WebRequest a HttpWebRequest y estableciendo las propiedades como httpWebReq.Referer ="http://stackoverflow.com"
, pero esto solo funciona para un puñado de encabezados que están expuestos a través de propiedades.
Me gustaría saber si hay una manera de obtener un control más detallado sobre la modificación de los encabezados con una solicitud de un recurso remoto.
Cada vez que cambie los encabezados de una HttpWebRequest
, debe usar las propiedades adecuadas en el objeto en sí, si es que existen. Si tiene una WebRequest
simple, asegúrese de convertirla a HttpWebRequest
primero. A continuación, se puede acceder a Referrer
en su caso a través de la ((HttpWebRequest)request).Referrer
, por lo que no necesita modificar directamente el encabezado; simplemente establezca la propiedad en el valor correcto. ContentLength
, ContentType
, UserAgent
, etc., todos deben configurarse 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()
debe llamar automáticamente a la propiedad adecuada detrás de las escenas, si eso es lo que quieren hacer.
Estoy usando solo:
request.ContentType = "application/json; charset=utf-8"
Las respuestas anteriores están bien, pero la esencia del problema es que algunos encabezados se establecen de una manera y otros se configuran de otras maneras. Ver arriba para las listas de ''encabezado restringido''. Para estos, simplemente los configura como una propiedad. Para otros, realmente agregas el encabezado. Mira aquí.
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "application/json";
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + info.clientId + ":" + info.clientSecret);
Me encontré con este problema con un cliente web personalizado. Creo que la gente puede confundirse debido a las múltiples formas de hacer esto. Al usar WebRequest.Create()
puede convertir a HttpWebRequest
y usar la propiedad para agregar o modificar un encabezado. Al usar un WebHeaderCollection
, puede usar .Add("referer","my_url")
.
Ex 1
WebClient client = new WebClient();
client.Headers.Add("referer", "http://.com");
client.Headers.Add("user-agent", "Mozilla/5.0");
Ex 2
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Referer = "http://.com";
request.UserAgent = "Mozilla/5.0";
response = (HttpWebResponse)request.GetResponse();
Puede simplemente enviar la WebRequest a una HttpWebRequest que se muestra a continuación:
var request = (HttpWebRequest)WebRequest.Create(myUri);
y luego, en lugar de tratar de manipular la lista de encabezado, aplíquela directamente en la solicitud de propiedad request.Referer:
request.Referer = "yourReferer";
Estas propiedades están disponibles en el objeto de solicitud.
Si necesita la 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 ...
Este problema también lo resolví 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 luego debe modificar su valor utilizando la propiedad adecuada (el indizador, por ejemplo), en lugar de intentar agregarlo nuevamente.
1.2 Cada vez que cambie los encabezados de una
HttpWebRequest
, debe usar las propiedades adecuadas en el objeto en sí, si existen.
Gracias FOR y Jvenema por las pautas principales ...
Pero, lo que descubrí, y esa fue la pieza que falta en el rompecabezas es que:
2.1 La clase
WebHeaderCollection
generalmente se accede a través deWebRequest
.Heading oWebResponse
.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 modificar.
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 enfrente 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, a partir de comentarios, comentario del usuario Kaido )
La solución es comprobar si el encabezado ya existe o está restringido (
WebHeaderCollection.IsRestricted(key)
) antes de llamar add
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
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.SetRawHeader("content-type", "application/json");
Clase de extensión
public static class HttpWebRequestExtensions
{
static string[] RestrictedHeaders = new string[] {
"Accept",
"Connection",
"Content-Length",
"Content-Type",
"Date",
"Expect",
"Host",
"If-Modified-Since",
"Keep-Alive",
"Proxy-Connection",
"Range",
"Referer",
"Transfer-Encoding",
"User-Agent"
};
static Dictionary<string, PropertyInfo> HeaderProperties = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);
static HttpWebRequestExtensions()
{
Type type = typeof(HttpWebRequest);
foreach (string header in RestrictedHeaders)
{
string propertyName = header.Replace("-", "");
PropertyInfo headerProperty = type.GetProperty(propertyName);
HeaderProperties[header] = headerProperty;
}
}
public static void SetRawHeader(this HttpWebRequest request, string name, string value)
{
if (HeaderProperties.ContainsKey(name))
{
PropertyInfo property = HeaderProperties[name];
if (property.PropertyType == typeof(DateTime))
property.SetValue(request, DateTime.Parse(value), null);
else if (property.PropertyType == typeof(bool))
property.SetValue(request, Boolean.Parse(value), null);
else if (property.PropertyType == typeof(long))
property.SetValue(request, Int64.Parse(value), null);
else
property.SetValue(request, value, null);
}
else
{
request.Headers[name] = value;
}
}
}
Escenarios
Escribí un contenedor para HttpWebRequest
y no quería exponer los 13 encabezados restringidos como propiedades en mi envoltorio. En su lugar, quería utilizar un Dictionary<string, string>
simple Dictionary<string, string>
.
Otro ejemplo es un proxy HTTP donde necesita tomar encabezados en una solicitud y reenviarlos al destinatario.
Hay muchos otros escenarios donde simplemente no es práctico o posible usar propiedades. Obligar 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. El lado positivo es que el reflejo se abstrae, sigue siendo rápido (0,001 segundos en mis pruebas) y como método de extensión se siente natural.
Notas
Los nombres de encabezado son insensibles a las mayúsculas y minúsculas según el RFC, http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
Tuve la misma excepción cuando mi código intentó establecer el valor del encabezado "Aceptar" como este:
WebRequest request = WebRequest.Create("http://someServer:6405/biprws/logon/long");
request.Headers.Add("Accept", "application/json");
La solución fue cambiarlo a esto:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://someServer:6405/biprws/logon/long");
request.Accept = "application/json";
WebRequest es abstracto (y dado que cualquier clase WebRequest debe anular la propiedad Headers) ... ¿qué WebRequest concreto está usando? En otras palabras, ¿cómo logras que ese objeto WebRequest se vincule?
ehr .. mnour respuesta me hizo darme cuenta de que el mensaje de error que estaba recibiendo es realmente acertado: le dice que el encabezado que está tratando de agregar ya existe y luego debe modificar su valor usando la propiedad apropiada (el indexador, por ejemplo ), en lugar de intentar agregarlo de nuevo. Eso es probablemente todo lo que estabas buscando.
Otras clases heredadas de WebRequest pueden tener incluso mejores propiedades que envuelven ciertos encabezados; Ver esta publicación, por ejemplo.