我试图设置一个HttpClient对象的Content-Type头作为我调用的API所要求的。
我试着像下面这样设置内容类型:
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");
// ...
}
它允许我添加Accept头,但当我尝试添加Content-Type时,它会抛出以下异常:
误用头名称。确保请求头与一起使用
HttpRequestMessage,带有HttpResponseMessage的响应头,以及
内容头与HttpContent对象。
如何在HttpClient请求中设置内容类型报头?
如果你不介意一个小的库依赖,Flurl。Http[披露:我是作者]使这个超级简单。它的PostJsonAsync方法负责序列化内容和设置内容类型报头,而ReceiveJson则反序列化响应。如果accept头是必需的,你需要自己设置,但Flurl提供了一个非常干净的方式来做到这一点:
using Flurl.Http;
var result = await "http://example.com/"
.WithHeader("Accept", "application/json")
.PostJsonAsync(new { ... })
.ReceiveJson<TResult>();
Flurl使用HttpClient和Json。它是一个PCL,所以它可以在各种平台上工作。
PM> Install-Package Flurl.Http
var content = new JsonContent();
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"));
这就是你所需要的。
使用Newtonsoft。Json,如果你需要一个内容为Json字符串。
public class JsonContent : HttpContent
{
private readonly MemoryStream _stream = new MemoryStream();
~JsonContent()
{
_stream.Dispose();
}
public JsonContent(object value)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
{
var serializer = new JsonSerializer();
serializer.Serialize(jw, value);
jw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
private JsonContent(string content)
{
Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var contexStream = new MemoryStream())
using (var sw = new StreamWriter(contexStream))
{
sw.Write(content);
sw.Flush();
contexStream.Position = 0;
contexStream.WriteTo(_stream);
}
_stream.Position = 0;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return _stream.CopyToAsync(stream);
}
protected override bool TryComputeLength(out long length)
{
length = _stream.Length;
return true;
}
public static HttpContent FromFile(string filepath)
{
var content = File.ReadAllText(filepath);
return new JsonContent(content);
}
public string ToJsonString()
{
return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
}
}
如果你不介意一个小的库依赖,Flurl。Http[披露:我是作者]使这个超级简单。它的PostJsonAsync方法负责序列化内容和设置内容类型报头,而ReceiveJson则反序列化响应。如果accept头是必需的,你需要自己设置,但Flurl提供了一个非常干净的方式来做到这一点:
using Flurl.Http;
var result = await "http://example.com/"
.WithHeader("Accept", "application/json")
.PostJsonAsync(new { ... })
.ReceiveJson<TResult>();
Flurl使用HttpClient和Json。它是一个PCL,所以它可以在各种平台上工作。
PM> Install-Package Flurl.Http
对于那些想要专门将Content-Type设置为Json的人,你可以使用扩展方法PostAsJsonAsync。
using System.Net.Http.Json; //this is needed for PostAsJsonAsync to work
//....
HttpClient client = new HttpClient();
HttpResponseMessage response = await
client.PostAsJsonAsync("http://example.com/" + "relativeAddress",
new
{
name = "John Doe",
age = 33
});
//Do what you need to do with your response
这样做的好处是代码更简洁,并且可以避免字符串化的json。更多详情请访问:https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944339(v=vs.118)
Api返回
"不支持的媒体类型","状态":415
添加ContentType到jsonstring做了魔法,这是我的脚本工作100%到今天为止
using (var client = new HttpClient())
{
var endpoint = "api/endpoint;
var userName = "xxxxxxxxxx";
var passwd = "xxxxxxxxxx";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
client.BaseAddress = new Uri("https://example.com/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
HttpResponseMessage response = await client.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
// Get the URI of the created resource.
Uri returnUrl = response.Headers.Location;
Console.WriteLine(returnUrl);
}
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}