tutorial paso example ejemplo crear consumir c# asp.net api http rest

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 con HttpResponseMessage y los encabezados de contenido con objetos HttpContent .

¿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.