调整MVC 4 WebApi XmlSerializer以丢失nameSpace

我正在开发一个MVC WebAPI,它使用EF和POCO类进行存储。 我想要做的是从XML中删除命名空间,以便端点返回并接受没有它的xml对象。 (json工作得很好)

 22   testas@email.com  ... 

我想这个工作

   22   testas@email.com  ... 

希望无需用一堆属性来装饰POCO。

我为此设置了一个测试解决方案,事实上,这些方法很受欢迎(必须是我系统中的其他一些问题)。 无论如何 – 我使用这个解决方案的结果是:

   22 TestAcc   Test@Test.com   

摆脱了顶部的架构,但现在搞砸了属性:(这是一个示例项目的链接

这里的答案是从ASP.NET Web API中删除XML中的命名空间的标记。

如果您根本不想装饰您的POCO,请使用第一个选项:

 config.Formatters.XmlFormatter.UseXmlSerializer = true; 

如果使用选项2,则可能需要添加对System.Runtime.Serialization的引用

假设这样的post接受设置正确:

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" }; } } 

}

配置(App_Start / WebApiConfig)

 //(Use this is you don't go the data contact and model annotation route) config.Formatters.XmlFormatter.UseXmlSerializer = true; 

结果

(带注释和数据联系):

 Test 

或者(使用XML序列化程序路由):

 Test 

也许你可以试试这个:

将默认的XmlFormatter替换为您自己的:

 GlobalConfiguration.Configuration.Formatters.Add(new CustomXmlFormatter()); GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 

并使用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); } }); } } 

自定义XML序列化程序从这里被盗,因此未经测试。

这应该序列化没有编写命名空间的对象。 我不确定它是否可以用于反序列化OOTB,你可能不得不尝试提供事件并处理UnknownElement或UnknownNode事件的XmlSerializer.Deserialize() 重载 。

自从我搞砸MVC 4以来已经有一段时间了,但我们最终用XmlSerializer替换了默认的格式化程序,如下所示:

 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = GetSerializeSettings(); GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true; } internal JsonSerializerSettings GetSerializeSettings() { return new JsonSerializerSettings { Formatting = Formatting.Indented, ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List { new IsoDateTimeConverter() } }; } 

这可能会有所帮助……我知道我们也使用你说你不想做的POCO上的属性来定制属性名称,但那是因为我们希望它们是驼峰式的。

我已经定制了Boris对MVC Webapi 5的回答。使用以下任一http头使用CustomFormatter渲染结果:

接受:application / xml

接受:text / xml

WebApiConfig.cs:

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); GlobalConfiguration.Configuration.Formatters.Add(new CustomXmlFormatter()); GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); } } 

CustomXmlFormatter.cs:

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Web; using System.Xml.Serialization; namespace Custom.Formatter { public class CustomXmlFormatter: MediaTypeFormatter { private UTF8Encoding encoder; public CustomXmlFormatter() { SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml")); SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml")); encoder = new UTF8Encoding(false, true); } public override bool CanReadType(Type type) { if (type == (Type)null) throw new ArgumentNullException("type"); //Type filtering if (type == typeof(SendEmailMessageResponse) || type == typeof(SendSmsMessageResponse)) return true; else return false; } public override bool CanWriteType(Type type) { return true; } public override Task ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger) { return Task.Factory.StartNew(() => { using (var streamReader = new StreamReader(stream, encoder)) { var serializer = new XmlSerializer(type); return serializer.Deserialize(streamReader); } }); } public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) { var serializer = new XmlSerializer(type); return Task.Factory.StartNew(() => { using (var streamWriter = new StreamWriter(stream, encoder)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); serializer.Serialize(streamWriter, value, ns); } }); } } }