Mar*_*rty 13 c# xml asp.net-mvc xml-serialization asp.net-web-api
我正在开发一个MVC WebAPI,它使用EF和POCO类进行存储.我想要做的是从XML中删除命名空间,以便端点返回并接受没有它的xml对象.(json工作得很好)
<ACCOUNT xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Platform.Services.AccountService.Data">
<id>22</id>
<City i:nil="true"/>
<Country i:nil="true"/>
<Email>testas@email.com</Email>
<Phone i:nil="true"/> ...
Run Code Online (Sandbox Code Playgroud)
我希望这能奏效
<ACCOUNT>
<id>22</id>
<City i:nil="true"/>
<Country i:nil="true"/>
<Email>testas@email.com</Email>
<Phone i:nil="true"/> ...
Run Code Online (Sandbox Code Playgroud)
希望无需用一堆属性来装饰POCO.
我为此设置了一个测试解决方案,实际上,这些方法正在受到欢迎(必须是我系统中的其他一些问题).无论如何 - 我使用这个解决方案的结果是:
<ArrayOfAccount>
<Account>
<id>22</id>
<name>TestAcc</name>
<parentid xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance" d3p1:nil="true"/>
<status_id xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance" d3p1:nil="true"/>
<Email>Test@Test.com</Email>
</Account>
</ArrayOfAccount>
Run Code Online (Sandbox Code Playgroud)
摆脱了顶部的架构,但现在搞砸了属性:(这是一个示例项目的链接
Mar*_*nes 13
这里的答案是从ASP.NET Web API中标记删除XML中的命名空间.
如果您根本不想装饰您的POCO,请使用第一个选项:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Run Code Online (Sandbox Code Playgroud)
如果使用选项2,则可能需要添加引用 System.Runtime.Serialization
假设这样的帖子接受设置正确:
GET http:// ANY OLD SERVER/api/foos/5接受:application/xml
调节器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Web.Http;
namespace CutomXmlFormater.Controllers
{
//[DataContract(Namespace = "")]
public class Foo
{
//[DataMember]
public string Bar { get; set; }
}
public class FoosController : ApiController
{
// GET api/foos/5
public Foo Get(int id)
{
return new Foo() { Bar = "Test" };
}
}
Run Code Online (Sandbox Code Playgroud)
}
配置(App_Start/WebApiConfig)
//(Use this is you don't go the data contact and model annotation route)
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Run Code Online (Sandbox Code Playgroud)
结果
(带注释和数据联系):
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Bar>Test</Bar></Foo>
Run Code Online (Sandbox Code Playgroud)
或者(使用XML序列化程序路由):
<Foo xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Bar>Test</Bar></Foo>
Run Code Online (Sandbox Code Playgroud)
也许你可以试试这个:
将默认的XmlFormatter替换为您自己的:
GlobalConfiguration.Configuration.Formatters.Add(new CustomXmlFormatter());
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Run Code Online (Sandbox Code Playgroud)
并使用XmlSerializer强制它,在序列化期间指定空命名空间,如下所示:
public CustomXmlFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
Encoding = new UTF8Encoding(false, true);
}
protected override bool CanReadType(Type type)
{
if (type == (Type)null)
throw new ArgumentNullException("type");
if (type == typeof(IKeyValueModel))
return false;
return true;
}
protected override bool CanWriteType(Type type)
{
return true;
}
protected override Task OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
{
return Task.Factory.StartNew(() =>
{
using (var streamReader = new StreamReader(stream, Encoding))
{
var serializer = new XmlSerializer(type);
return serializer.Deserialize(streamReader);
}
});
}
protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, System.Net.TransportContext transportContext)
{
var serializer = new XmlSerializer(type);
return Task.Factory.StartNew(() =>
{
using (var streamWriter = new StreamWriter(stream, Encoding))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
serializer.Serialize(streamWriter, value, ns);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
自定义XML序列化程序从这里被盗,因此未经测试.
这应该序列化没有编写命名空间的对象.我不确定它是否可以用于反序列化OOTB,你可能不得不尝试XmlSerializer.Deserialize() 提供事件并处理UnknownElement或UnknownNode事件的重载.