如何从 HttpClient.PostAsJsonAsync() 生成的 Content-Type 标头中删除 charset=utf8?
Posted
技术标签:
【中文标题】如何从 HttpClient.PostAsJsonAsync() 生成的 Content-Type 标头中删除 charset=utf8?【英文标题】:How to remove charset=utf8 from Content-Type header generated by HttpClient.PostAsJsonAsync()? 【发布时间】:2014-04-18 19:41:41 【问题描述】:我有一个问题 HttpClient.PostAsJsonAsync()
除了“Content-Type”标头中的“application/json”之外,该方法还添加了“charset=utf-8”
所以标题看起来像这样:
内容类型:应用程序/json;字符集=utf-8
虽然 ASP.NET WebAPI 对此标头没有任何问题,但我发现我作为客户端使用的其他 WebAPI 不接受带有此标头的请求,除非它只是 application/json。
在使用 PostAsJsonAsync() 时,是否可以从 Content-Type 中删除“charset=utf-8”,还是应该使用其他方法?
解决方案: 感谢 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());
【问题讨论】:
更多更好的解决方案:***.com/questions/40273638/… 【参考方案1】:您可以从 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);
【讨论】:
有效!我不敢相信必须为此做如此尴尬的工作,但它确实有效!非常感谢 @oronbz 服务器应该接受字符集。您必须做的事情永远不会成为问题。话虽如此,当您只使用派生的 HttpContent 类而不是依赖于格式化程序时,直接处理 HTTP 要容易得多。 @DarrelMiller 感谢您的评论。当您是客户端而不是服务器时,“应该” 是一个没有意义的词。我还处理了一个 API,他们期望 "Accept" 标头在 POST 请求中完全没有意义,并且 HttpClient 不允许将 Accept 标头插入到 POST 所以我不得不使用 TryAddHeaderWithoutValidation() 来解决它。您能否提供一个推荐示例? @oronbz “应该”评论是对为什么没有简单的方法来解决您的问题的理由。我并没有否认这是一个需要处理的真正问题。请参阅我的其他答案,作为有关如何处理 HTTP 有效负载并更好地控制它们的建议。【参考方案2】:为了更直接地控制您发送的有效负载,您可以创建派生的 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。
就我个人而言,我发现它可以让我更好地控制我的有效载荷。
【讨论】:
感谢这个解决方案伙伴,我会在需要额外控制时使用它。【参考方案3】:我更喜欢 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);
不用说,您可以将其调整为适合您需要的任何基类。希望对某人有所帮助。
【讨论】:
不用说,如果你使用这个确切的例子,你就需要自己进行序列化了。以上是关于如何从 HttpClient.PostAsJsonAsync() 生成的 Content-Type 标头中删除 charset=utf8?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从回收器适配器发送到片段 |如何从 recyclerview 适配器调用片段函数
如何从服务器获取和设置 android 中的 API(从服务器获取 int 值)?如何绑定和实现这个