我错过了一个新的webapi技巧 - 我试图通过一个帖子请求提交一个xml字符串而没有太多运气。
前端正在使用这样的jQuery:
$(document = function () {
$("#buttonTestAPI").click(function () {
var d = " <customer><customer_id>1234</customer_id></customer>";
$.ajax({
type: 'POST',
contentType: "text/xml",
url: "@Url.Content("~/api/Customer/")",
data: d,
success: function (result) {
var str = result;
$("#output").html(str);
}
});
});
});
我的控制器目前非常简单 - 只是后期操作的默认设置 - 尝试返回传入的内容:
public string Post(string value)
{
return value;
}
但是,“值”重复为空。奇怪的是,当我在jquery中更改我的数据时,就像这样:
d = "<customer_id>1234</customer_id>";
然后我在控制器中得到“值”为1234。
如何访问控制器中更复杂的xml字符串?
答案 0 :(得分:18)
以下内容允许您通过POST将原始XML消息读取到Web API方法:
public void PostRawXMLMessage(HttpRequestMessage request)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(request.Content.ReadAsStreamAsync().Result);
}
您可以调试和检查正文,标题等,并会看到发布的原始XML。我使用Fiddler的Composer进行HTTP POST,这很有效。
答案 1 :(得分:13)
您发送的内容类型为text/xml
,但您已将参数定义为string
。理想情况下,您的XML应映射到类,以便反序列化。
因此,如果您需要 raw xml ,那么它还不受支持。 Web API目前已准备好用于序列化MediaTypeFormatters和缺少简单类型格式化程序,但它们可以轻松构建。
这是格式化程序的最小实现,只支持在您的情况下读取并基于测试版安装程序(而不是夜间源代码,因为它已经发生了实质性更改):
public class TextMediaTypeFormatter : MediaTypeFormatter
{
public TextMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
}
protected override bool CanReadType(Type type)
{
return type == typeof (string);
}
protected override System.Threading.Tasks.Task<object> OnReadFromStreamAsync(Type type, Stream stream,
HttpContentHeaders contentHeaders,
FormatterContext formatterContext)
{
var taskCompletionSource = new TaskCompletionSource<object>();
try
{
var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
taskCompletionSource.SetResult(s);
}
catch (Exception e)
{
taskCompletionSource.SetException(e);
}
return taskCompletionSource.Task;
}
}
要使用它,只需将其添加到格式化程序集合中:
GlobalConfiguration.Configuration.Formatters.Insert(0, new TextMediaTypeFormatter());
答案 2 :(得分:6)
任何人都在寻找更新版本的Aliostad上面的答案,从测试版发布到asp.net mvc 4 web api的RC(微小的变化导致了我的轻微修改)。
public class TextMediaTypeFormatter : MediaTypeFormatter
{
public TextMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
}
public override bool CanReadType(Type type)
{
if (type == typeof(String))
return true;
else
return false;
}
public override bool CanWriteType(Type type)
{
if (type == typeof(String))
return true;
else
return false;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
{
var taskCompletionSource = new TaskCompletionSource<object>();
try
{
var memoryStream = new MemoryStream();
readStream.CopyTo(memoryStream);
var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
taskCompletionSource.SetResult(s);
}
catch (Exception e)
{
taskCompletionSource.SetException(e);
}
return taskCompletionSource.Task;
}
}
答案 3 :(得分:0)
为我解决这个问题的原因是添加了这个:
static SubscriberController()
{
//Needed for xml deserialization to work
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
}
(SubscriberController
是我的类,它扩展了ApiController
,上面是一个静态构造函数,因此它将运行一次。)
不确定是否还有必要,但我将[FromBody]
属性添加到我的参数中,如下所示:
public async Task<HttpResponseMessage> SynchronizeImax( [FromBody] SynchronizeRequest synchronizeRequest )
{
//...
}
这样做的好处是可以无缝地处理XML和JSON输入。