Here's my solution. There were several issues I had to face: which binding to choose (WebHttpBinding), dealing with PostAsync (async within sync method) and preventing StringWriter to change UTF8 to UTF16.
On the server side, the interface looks like this:
[ServiceContract]
[XmlSerializerFormat]
public interface IHelloWorld
{
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "")]
void HelloWorld(MyRequest request);
}
The attribute XmlSerializerFormat indicates that WCF should use the XMLSerializer instead of the default DataContractSerializer. In order for this to work the class MyRequest has to be properly annotated with [XmlElement], [XmlAttribute], etc., see https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-the-xmlserializer-class.
This is where I configure the WCF host:
WebServiceHost host = new WebServiceHost(typeof(HelloWorldService));
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
var endpoint = host.AddServiceEndpoint(typeof(IHelloWorld), binding, _address);
endpoint.Behaviors.Add(new WebHttpBehavior());
host.Open();
On the client side, the code now looks like this:
var _serializer = new XmlSerializer(typeof(MyRequest));
StringContent _httpContent;
// We need to keep UTF8 encoding here (StringWriter uses UTF16 by default)
using (StringWriter _textWriter = new Utf8StringWriter())
{
_serializer.Serialize(_textWriter, _ebicsRequest);
_httpContent = new StringContent(_textWriter.ToString(), Encoding.UTF8, "application/xml");
}
HttpClient _httpClient = new HttpClient();
var task = _httpClient.PostAsync(_requestURI, _httpContent).Result;
I found the Utf8StringWriter class here: https://stackoverflow.com/a/25731993/9266796.