我有一个问题 HttpClient.PostAsJsonAsync()
除了" application / json"在" Content-Type"标题方法还添加" charset = utf-8"
所以标题看起来像这样:
Content-Type:application / json;字符集= UTF-8
虽然ASP.NET WebAPI对此标题没有任何问题,但我发现我作为客户端工作的其他WebAPI不接受带有此标头的请求,除非它&#39 ; s只有application / json。
无论如何要删除" charset = utf-8"使用PostAsJsonAsync()时来自Content-Type,还是应该使用其他方法?
解: 致Yishai的信用!
using System.Net.Http.Headers;
public class NoCharSetJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType.CharSet = "";
}
}
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PostAsJsonWithNoCharSetAsync<T>(this HttpClient client, string requestUri, T value, CancellationToken cancellationToken)
{
return await client.PostAsync(requestUri, value, new NoCharSetJsonMediaTypeFormatter(), cancellationToken);
}
public static async Task<HttpResponseMessage> PostAsJsonWithNoCharSetAsync<T>(this HttpClient client, string requestUri, T value)
{
return await client.PostAsync(requestUri, value, new NoCharSetJsonMediaTypeFormatter());
}
}
答案 0 :(得分:6)
您可以从JsonMediaTypeFormatter派生并覆盖SetDefaultContentHeaders。
致电base.SetDefaultContentHeaders()
,然后清除headers.ContentType.CharSet
然后根据以下代码编写自己的扩展方法:
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, CancellationToken cancellationToken)
{
return client.PostAsync(requestUri, value,
new JsonMediaTypeFormatter(), cancellationToken);
}
本质上是这样的:
public static Task<HttpResponseMessage> PostAsJsonWithNoCharSetAsync<T>(this HttpClient client, string requestUri, T value, CancellatioNToken cancellationToken)
{
return client.PostAsync(requestUri, value,
new NoCharSetJsonMediaTypeFormatter(), cancellationToken);
}
答案 1 :(得分:4)
为了更直接地控制您发送的有效负载,您可以创建派生的HttpContent类,而不是让您的对象传递给ObjectContent类,然后将流委托给Formatter类。
支持读写的JsonContent类看起来像这样,
public class JsonContent : HttpContent
{
private readonly Stream _inboundStream;
private readonly JToken _value;
public JsonContent(JToken value)
{
_value = value;
Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
public JsonContent(Stream inboundStream)
{
_inboundStream = inboundStream;
}
public async Task<JToken> ReadAsJTokenAsync()
{
return _value ?? JToken.Parse(await ReadAsStringAsync());
}
protected async override Task<Stream> CreateContentReadStreamAsync()
{
return _inboundStream;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
if (_value != null)
{
var jw = new JsonTextWriter(new StreamWriter(stream)) {Formatting = Formatting.Indented};
_value.WriteTo(jw);
jw.Flush();
} else if (_inboundStream != null)
{
return _inboundStream.CopyToAsync(stream);
}
return Task.FromResult<object>(null);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_inboundStream.Dispose();
}
base.Dispose(disposing);
}
}
一旦你上了这门课,你就可以了,
var content = new JsonContent(myObject);
_httpClient.PostAsync(uri,content);
如果您需要更改任何内容标题,您可以在发送请求之前手动执行此操作。如果你需要处理任何请求标头,那么你使用SendAsync重载,
var content = new JsonContent(myObject);
// Update Content headers here
var request = new HttpRequestMessage {RequestUri = uri, Content = content };
// Update request headers here
_httpClient.SendAsync(request);
对于几乎任何媒体类型或任何数据源,都可以轻松创建派生内容类。我已经创建了从HttpContent派生的各种类。例如FileContent,EmbeddedResourceContent,CSVContent,XmlContent,ImageContent,HalContent,CollectionJsonContent,HomeContent,ProblemContent。
就个人而言,我发现它可以让我更好地控制我的有效载荷。
答案 2 :(得分:-1)
我更喜欢Darrel的答案,但对于我来说它仍然太复杂了。我用过这个:
public class ContentTypeSpecificStringContent : StringContent
{
/// <summary>
/// Ensure content type is reset after base class mucks it up.
/// </summary>
/// <param name="content">Content to send</param>
/// <param name="encoding">Encoding to use</param>
/// <param name="contentType">Content type to use</param>
public ContentTypeSpecificStringContent(string content, Encoding encoding, string contentType)
: base(content, encoding, contentType)
{
Headers.ContentType = new MediaTypeHeaderValue(contentType);
}
}
毋庸置疑,您可以根据自己的需求调整适合自己的基类。希望能有所帮助。