paso - web api json c#
¿Cómo configura el encabezado Content-Type para una solicitud HttpClient? (9)
.Net intenta forzarlo a obedecer ciertos estándares, a saber, que el encabezado Content-Type
solo se puede especificar en solicitudes que tienen contenido (por ejemplo, POST
, PUT
, etc.). Por lo tanto, como otros lo han indicado, la forma preferida de establecer el encabezado Content-Type
es a través de la propiedad HttpContent.Headers.ContentType
.
Dicho esto, ciertas API (como LiquidFiles Api , a partir de 2016-12-19) requieren establecer el encabezado Content-Type
para una solicitud GET
. .Net no permitirá establecer este encabezado en la solicitud en sí, incluso utilizando TryAddWithoutValidation
. Además, no puede especificar un Content
para la solicitud, incluso si es de longitud cero. La única forma en la que podía parecer que era evitar esto era recurrir a la reflexión. El código (en caso de que otra persona lo necesite) es
var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
?? typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
var invalidFields = (HashSet<string>)field.GetValue(null);
invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");
Editar:
Como se señaló en los comentarios, este campo tiene diferentes nombres en diferentes versiones de la dll. En el código fuente de GitHub , el campo actualmente se llama s_invalidHeaders
. El ejemplo ha sido modificado para dar cuenta de esto por la sugerencia de @David Thompson.
Estoy intentando establecer el encabezado Content-Type
de un objeto HttpClient
como lo requiere una API a la que llamo.
He intentado configurar el tipo de Content-Type
como a continuación:
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri("http://example.com/");
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
// ...
}
Me permite agregar el encabezado Accept
pero cuando intento agregar Content-Type
se produce la siguiente excepción:
Nombre del encabezado mal utilizado. Asegúrese de que los encabezados de solicitud se utilicen con
HttpRequestMessage
, los encabezados de respuesta conHttpResponseMessage
y los encabezados de contenido con objetosHttpContent
.
¿Cómo puedo configurar el encabezado Content-Type
en una solicitud HttpClient
?
Alguna información adicional sobre .NET Core (después de leer la publicación de erdomke sobre la configuración de un campo privado para suministrar el tipo de contenido en una solicitud que no tiene contenido) ...
Después de depurar mi código, no puedo ver el campo privado para establecer a través de la reflexión, así que pensé que intentaría recrear el problema.
He probado el siguiente código usando .Net 4.6:
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
Task<HttpResponseMessage> response = client.SendAsync(httpRequest); //I know I should have used async/await here!
var result = response.Result;
Y, como era de esperar, obtengo una excepción agregada con el contenido "Cannot send a content-body with this verb-type."
Sin embargo, si hago lo mismo con .NET Core (1.1), no obtengo una excepción. Mi solicitud del servidor respondió muy felizmente a mi solicitud, y se recogió el tipo de contenido.
Me sorprendió gratamente por eso, ¡y espero que ayude a alguien!
El tipo de contenido es un encabezado del contenido, no de la solicitud, por lo que esto está fallando. AddWithoutValidation
como lo sugiere Robert Levy puede funcionar, pero también puede configurar el tipo de contenido al crear el contenido de la solicitud en sí (tenga en cuenta que el fragmento de código agrega "application / json" en dos lugares, para los encabezados Aceptar y Tipo de Contenido):
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{/"name/":/"John Doe/",/"age/":33}",
Encoding.UTF8,
"application/json");//CONTENT-TYPE header
client.SendAsync(request)
.ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
Llame a AddWithoutValidation
lugar de Add
(vea este enlace de MSDN ).
Alternativamente, supongo que la API que está utilizando realmente solo requiere esto para las solicitudes POST o PUT (no las solicitudes GET normales). En ese caso, cuando llame a HttpClient.PostAsync
y pase un HttpContent
, establezca esto en la propiedad Headers
de ese objeto HttpContent
.
Ok, no es HTTPClient pero si puedes usarlo, WebClient es bastante fácil:
using (var client = new System.Net.WebClient())
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json; charset=utf-8");
client.DownloadString(...);
}
Para aquellos que no vieron el comentario de John a la solución de carlos ...
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
Si no te importa una pequeña dependencia de la biblioteca, Flurl.Http [revelación: Soy el autor] hace que esto sea súper simple. Su método PostJsonAsync
se encarga de serializar el contenido y configurar el encabezado de content-type
, y ReceiveJson
deserializa la respuesta. Si se requiere el encabezado de accept
, deberá configurarlo usted mismo, pero Flurl también ofrece una forma bastante clara de hacerlo:
using Flurl.Http;
var result = await "http://example.com/"
.WithHeader("Accept", "application/json")
.PostJsonAsync(new { ... })
.ReceiveJson<TResult>();
Flurl usa HttpClient y Json.NET debajo del capó, y es un PCL, por lo que funcionará en una variedad de plataformas.
PM> Install-Package Flurl.Http
intenta usar TryAddWithoutValidation
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
var content = new HttpContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));
Es todo lo que necesitas.