调整MVC 4 WebApi XmlSerializer以丢失nameSpace

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)


Bor*_* B. 6

也许你可以试试这个:

将默认的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() 提供事件并处理UnknownElementUnknownNode事件的重载.