Los*_*les 5 c# xml xml-serialization xml-namespaces asp.net-mvc-4
我目前正在从事一个项目,该项目需要我从其端点与JSON一起输出XML。我有以下模型:
[DataContract(Namespace="http://www.yale.edu/tp/cas")]
[XmlType("serviceResponse")]
[XmlRoot(Namespace="http://www.yale.edu/tp/cas")]
public class ServiceResponse
{
[XmlElement("authenticationSuccess")]
public AuthenticationSuccess Success { get; set; }
[XmlElement("authenticationFailure")]
public AuthenticationFailure Failure { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
成功不为空时,输出如下:
<serviceResponse>
<authenticationSuccess />
</serviceResponse>
Run Code Online (Sandbox Code Playgroud)
现在,我可以很明显地看到,我没有为分配给名称空间的前缀分配前缀。我的问题是我找不到使用媒体格式化程序在MVC4中添加名称空间前缀的位置。我的global.asax中包含以下内容:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
GlobalConfiguration.Configuration.Formatters.XmlFormatter.RemoveSerializer(typeof(Models.ServiceResponse));
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SetSerializer(typeof(Models.ServiceResponse), new Infrastructure.NamespaceXmlSerializer(typeof(Models.ServiceResponse)));
Run Code Online (Sandbox Code Playgroud)
我创建了一个基于XmlSerializer的自定义序列化程序,以尝试拦截写入请求并在此处添加名称空间列表。这种方法的问题是,现在我在每个可重写方法中都有断点,并且在序列化时都没有断点,这使我相信没有使用我的序列化器。
是否有一些内置的方法来完成我想做的事情,还是我不得不重新实现XmlMediaTypeFormatter以在序列化对象时传递名称空间?
作为后续答案:对我来说最简单的解决方案是编写自己的XmlMediaTypeFormatter
. 事实证明,它并不像我想象的那么令人生畏。
public class NamespacedXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
const string xmlType = "application/xml";
const string xmlType2 = "text/xml";
public XmlSerializerNamespaces Namespaces { get; private set; }
Dictionary<Type, XmlSerializer> Serializers { get; set; }
public NamespacedXmlMediaTypeFormatter()
: base()
{
this.Namespaces = new XmlSerializerNamespaces();
this.Serializers = new Dictionary<Type, XmlSerializer>();
}
public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
lock (this.Serializers)
{
if (!Serializers.ContainsKey(type))
{
var serializer = new XmlSerializer(type);
//we add a new serializer for this type
this.Serializers.Add(type, serializer);
}
}
return Task.Factory.StartNew(() =>
{
XmlSerializer serializer;
lock (this.Serializers)
{
serializer = Serializers[type];
}
var xmlWriter = new XmlTextWriter(writeStream, Encoding.UTF8);
xmlWriter.Namespaces = true;
serializer.Serialize(xmlWriter, value, this.Namespaces);
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是格式化程序的要点:https://gist.github.com/kcuzner/eef239003d4f99dfacea
格式化程序通过公开将要使用的XmlSerializerNamespaces
内容来工作。XmlSerializer
这样我就可以根据需要添加任意名称空间。
我的顶级模型如下所示:
[XmlRoot("serviceResponse", Namespace="http://www.yale.edu/tp/cas")]
public class ServiceResponse
{
[XmlElement("authenticationSuccess")]
public CASAuthenticationSuccess Success { get; set; }
[XmlElement("authenticationFailure")]
public CASAuthenticationFailure Failure { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在我的文件中Global.asax
,我添加了以下内容以将格式化程序放在列表的顶部:
var xmlFormatter = new Infrastructure.NamespacedXmlMediaTypeFormatter();
xmlFormatter.Namespaces.Add("cas", "http://www.yale.edu/tp/cas");
GlobalConfiguration.Configuration.Formatters.Insert(0, xmlFormatter);
Run Code Online (Sandbox Code Playgroud)
添加格式化程序并确保属性设置正确后,我的 XML 已正确命名。
就我而言,我需要添加cas
链接到http://www.yale.edu/tp/cas
. 对于其他使用此功能的人,只需更改/复制Add
对您心目中的内容的调用,添加命名空间即可。
归档时间: |
|
查看次数: |
1817 次 |
最近记录: |