[英]Adjust MVC 4 WebApi XmlSerializer to lose the nameSpace
我正在開發一個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"/> ...
我希望這能奏效
<ACCOUNT>
<id>22</id>
<City i:nil="true"/>
<Country i:nil="true"/>
<Email>testas@email.com</Email>
<Phone i:nil="true"/> ...
希望無需用一堆屬性來裝飾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>
擺脫了頂部的架構,但現在搞砸了屬性:(這是一個示例項目的鏈接
這里的答案是從ASP.NET Web API中標記刪除XML中的命名空間 。
如果您根本不想裝飾您的POCO,請使用第一個選項:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
如果使用選項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" };
}
}
}
配置(App_Start / WebApiConfig)
//(Use this is you don't go the data contact and model annotation route)
config.Formatters.XmlFormatter.UseXmlSerializer = true;
結果
(帶注釋和數據聯系):
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Bar>Test</Bar></Foo>
或者(使用XML序列化程序路由):
<Foo xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Bar>Test</Bar></Foo>
也許你可以試試這個:
將默認的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<JsonConverter> { 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<object> 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);
}
});
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.