Instead of using Flurl, I tried to achieve the same goal with HttpClient. That didnt work, so I created an extension method for Flurl instead.
https://stackoverflow.com/a/44543016/915414 suggests using StringContent to change the Content-Type:
var jobInJson = JsonConvert.SerializeObject(job);
var json = new StringContent(jobInJson, Encoding.UTF8);
json.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json; odata=verbose");
var flurClient = GetBaseUrlForOperations("Jobs");
return await flurClient.PostAsync(json).ReceiveJson<Job>();
Although this does change the Content-Type, the charset=utf-8 still remains.
I decompiled System.Net.Http.StringContent to see how it works. It defaults to a charset:
this.Headers.ContentType = new MediaTypeHeaderValue(mediaType == null ? "text/plain" : mediaType)
{
CharSet = encoding == null ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName
};
And guess what... At its core, PostUrlEncodedAsync uses StringContent.
So, I created an extension method for Flurl, that uses a similar implementation of StringContent, where CharSet = "";
PostUrlEncodedAsyncWithoutCharset:
public static class HttpExtensions
{
public static Task<HttpResponseMessage> PostUrlEncodedAsyncWithoutCharset(this IFlurlClient client, object data, CancellationToken cancellationToken = default(CancellationToken), HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
{
CapturedUrlContentCustom urlEncodedContent = new CapturedUrlContentCustom(client.Settings.UrlEncodedSerializer.Serialize(data));
return client.SendAsync(HttpMethod.Post, (HttpContent)urlEncodedContent, new CancellationToken?(cancellationToken), completionOption);
}
}
CapturedUrlContentCustom:
public class CapturedUrlContentCustom : CapturedStringContentCustom
{
public CapturedUrlContentCustom(string data)
: base(data, (Encoding) null, "application/x-www-form-urlencoded")
{
}
}
CapturedStringContentCustom:
public class CapturedStringContentCustom : CustomStringContent
{
public string Content { get; }
public CapturedStringContentCustom(string content, Encoding encoding = null, string mediaType = null)
: base(content, encoding, mediaType)
{
this.Content = content;
}
}
CustomStringContent:
public class CustomStringContent : ByteArrayContent
{
private const string defaultMediaType = "application/x-www-form-urlencoded";
public CustomStringContent(string content)
: this(content, (Encoding)null, (string)null)
{
}
public CustomStringContent(string content, Encoding encoding)
: this(content, encoding, (string)null)
{
}
public CustomStringContent(string content, Encoding encoding, string mediaType)
: base(CustomStringContent.GetContentByteArray(content, encoding))
{
this.Headers.ContentType = new MediaTypeHeaderValue(mediaType == null ? "application/x-www-form-urlencoded" : mediaType)
{
CharSet = ""
};
}
private static byte[] GetContentByteArray(string content, Encoding encoding)
{
if (content == null)
throw new ArgumentNullException(nameof(content));
if (encoding == null)
encoding = Encoding.UTF8;
return encoding.GetBytes(content);
}
}
Now, you can call PostUrlEncodedAsyncWithoutCharset and charset=utf-8 will not appear.