我目前正致力于一个解决方案,即有人通过Post向我们的API发送XML内容。
我使用下面的代码,当使用CURL使用PHP脚本提供XML内容时,它可以正常工作。当我使用C#对客户端进行相同的尝试时,我无法获得正确的XML内容。
服务器代码:
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using log4net;
public class BinaryTextMediaTypeFormatter : MediaTypeFormatter
{
/// <summary>
/// The _log.
/// </summary>
private readonly ILog log = LogManager.GetLogger(typeof(BinaryTextMediaTypeFormatter));
/// <summary>
/// Initializes a new instance of the <see cref="BinaryTextMediaTypeFormatter"/> class.
/// </summary>
public BinaryTextMediaTypeFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
}
/// <summary>
/// The read from stream async.
/// </summary>
/// <param name="type">
/// The type.
/// </param>
/// <param name="readStream">
/// The read stream.
/// </param>
/// <param name="content">
/// The content.
/// </param>
/// <param name="formatterLogger">
/// The formatter logger.
/// </param>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var taskCompletionSource = new TaskCompletionSource<object>();
try
{
var memoryStream = new MemoryStream();
readStream.CopyTo(memoryStream);
var streamValues = Encoding.Default.GetString(memoryStream.ToArray());
taskCompletionSource.SetResult(streamValues.Trim());
}
catch (Exception e)
{
this.log.Error(e);
taskCompletionSource.SetException(e);
}
return taskCompletionSource.Task;
}
/// <summary>
/// The can read type.
/// </summary>
/// <param name="type">
/// The type.
/// </param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
public override bool CanReadType(Type type)
{
return type == typeof(string);
}
/// <summary>
/// The can write type.
/// </summary>
/// <param name="type">
/// The type.
/// </param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
public override bool CanWriteType(Type type)
{
return false;
}
}
客户端代码(这个客户端代码有一个可以添加XML的文本框,一个用于打印响应的响应文本框和一个发送按钮):
/// <summary>
/// Initializes a new instance of the <see cref="Form1"/> class.
/// </summary>
public Form1()
{
this.InitializeComponent();
}
/// <summary>
/// The btn send_ click.
/// </summary>
/// <param name="sender">
/// The sender.
/// </param>
/// <param name="e">
/// The e.
/// </param>
private void BtnSendClick(object sender, EventArgs e)
{
try
{
var bytes = System.Text.Encoding.Default.GetBytes(this.txtContent.Text);
var postData = GetBytes(System.Text.Encoding.UTF8.GetString(bytes));
const string Uri = "http://dev.sportsdata.no/api/Api/FileClient/Odf";
byte[] response;
using (var client = new WebClient())
{
response = client.UploadData(Uri, "POST", postData);
}
this.txtResonse.Text += Environment.NewLine;
this.txtResonse.Text += @"response: " + response;
}
catch (Exception exception)
{
this.txtResonse.Text += Environment.NewLine + @"Starting loop" + Environment.NewLine;
foreach (KeyValuePair<string, string> kvp in exception.Data)
{
this.txtResonse.Text += @"key: " + kvp.Key + @", value: " + kvp.Value + Environment.NewLine;
}
this.txtResonse.Text += @"ending loop" + Environment.NewLine;
this.txtResonse.Text += @"exception: " + exception.Message + Environment.NewLine + exception.StackTrace;
}
}
/// <summary>
/// The get bytes.
/// </summary>
/// <param name="str">
/// The str.
/// </param>
/// <returns>
/// The <see cref="byte[]"/>.
/// </returns>
private static byte[] GetBytes(string str)
{
var bytes = new byte[str.Length * sizeof(char)];
Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
日志的一些输出:
This is the content: <2016-02-08 13:35:56,673 [13] ERROR 166ogger [(null)] [(null)] - System.Xml.XmlException: Name cannot begin with the '.' character, hexadecimal value 0x00. Line 1, position 2.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args)
at System.Xml.XmlTextReaderImpl.ParseQName(Boolean isQName, Int32 startOffset, Int32& colonPos)
at System.Xml.XmlTextReaderImpl.ParseElement()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)