ASP.NET MVC4 WebAPI 和发布 XML 数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10428177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC4 WebAPI and Posting XML data
提问by Thomas
I'm missing a trick with the new webapi - I'm trying to submit an xml string through a post request and not having much luck.
我错过了新 webapi 的一个技巧 - 我试图通过 post 请求提交一个 xml 字符串,但运气不佳。
The front end is using jQuery like this:
前端使用 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);
}
});
});
});
My controller is pretty simple at the moment - just the default for the post action - trying to return what was passed in:
我的控制器目前非常简单 - 只是 post 操作的默认值 - 试图返回传入的内容:
public string Post(string value)
{
return value;
}
However, "value" is repeatedly null. The odd thing is, when I change my data in the jquery to be something like this:
但是,“值”反复为空。奇怪的是,当我将 jquery 中的数据更改为如下所示时:
d = "<customer_id>1234</customer_id>";
Then I get "value" in my controller as 1234.
然后我在控制器中得到“值”为 1234。
How can I get access to the more complex xml string in my controller?
如何访问控制器中更复杂的 xml 字符串?
回答by atconway
The following will allow you to read a raw XML message via a POST to a Web API method:
以下将允许您通过 POST 到 Web API 方法读取原始 XML 消息:
public void PostRawXMLMessage(HttpRequestMessage request)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(request.Content.ReadAsStreamAsync().Result);
}
You can debug and inspect the body, headers, etc. and will see the raw XML posted. I used Fiddler's Composer to make a HTTP POST and this works well.
您可以调试和检查正文、标题等,并会看到发布的原始 XML。我使用 Fiddler 的 Composer 制作了一个 HTTP POST,效果很好。
回答by Aliostad
You are sending content type of text/xmlbut you have defined your parameter as string. Ideally your XML should be mapped to a classso that it can be deserialised.
您发送的内容类型为 ,text/xml但您已将参数定义为string。理想情况下,您的 XML 应该映射到一个类,以便它可以被反序列化。
So if you need raw xmlthen it is not supported yet. Web API currently is geared up for serialization MediaTypeFormatters and missing simple type formatters but they can easily built.
因此,如果您需要原始 xml,则尚不支持它。Web API 目前适用于序列化 MediaTypeFormatters 并缺少简单的类型格式化程序,但它们可以轻松构建。
This one is a minimalimplementation of such formatter supporting only read in your case and based on beta installer(and not nightly source code since it has substantially changed):
这是这种格式化程序的最小实现,仅支持在您的情况下读取并基于测试版安装程序(而不是每晚源代码,因为它已发生重大变化):
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;
}
}
And to use it, just add it to formatters collection:
要使用它,只需将其添加到格式化程序集合中:
GlobalConfiguration.Configuration.Formatters.Insert(0, new TextMediaTypeFormatter());
回答by BMac
Anyone looking for an updated version of Aliostad's answer above from the beta release to the RC of asp.net mvc 4 web api (minor changes resulted in a slight rework for me).
任何人都在寻找从测试版到 asp.net mvc 4 web api 的 RC 的上述 Aliostad 答案的更新版本(微小的变化导致对我的轻微返工)。
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;
}
}
回答by dario_ramos
What solved the issue for me was adding this:
为我解决问题的是添加以下内容:
static SubscriberController()
{
//Needed for xml deserialization to work
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
}
(SubscriberControlleris my class which extends ApiController, and the above is a static constructor, so it will run once).
(SubscriberController是我的扩展类,ApiController上面是一个静态构造函数,所以它会运行一次)。
Not sure if it also necessary, but I added the [FromBody]attribute to my parameter, like so:
不确定是否也有必要,但我将该[FromBody]属性添加到我的参数中,如下所示:
public async Task<HttpResponseMessage> SynchronizeImax( [FromBody] SynchronizeRequest synchronizeRequest )
{
//...
}
The great thing about doing it this way is that you can seamlessly handle both XML and JSON input.
这样做的好处在于您可以无缝地处理 XML 和 JSON 输入。

