ASP.NET Web API特定于控制器的序列化程序
我有一个带有2个控制器的自宿主Web API:ASP.NET Web API特定于控制器的序列化程序,asp.net,xml,xml-serialization,asp.net-web-api,Asp.net,Xml,Xml Serialization,Asp.net Web Api,我有一个带有2个控制器的自宿主Web API: public class CustomConfigAttribute : Attribute, IControllerConfiguration { public void Initialize(HttpControllerSettings settings, HttpControllerDescriptor descriptor) { settings.Formatters.XmlFormatter.Use
public class CustomConfigAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings settings,
HttpControllerDescriptor descriptor)
{
settings.Formatters.XmlFormatter.UseXmlSerializer = true;
}
}
- 对于控制器1,我需要默认的DataContractSerializer(我公开EF5POCO)
- 对于控制器2,我需要将参数UseXmlSerializer设置为true的XmlFormatter(我公开一个XmlDocument)
public class CustomConfigAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings settings,
HttpControllerDescriptor descriptor)
{
settings.Formatters.XmlFormatter.UseXmlSerializer = true;
}
}
如何解决这个问题?我想您可以编写一个自定义的
ActionFilterAttribute
在
OnActionExecuting
中,将原始值存储在HttpContext中,然后在OnActionExecuted
中,恢复原始值。控制器操作本身不应关心数据的序列化方式。yo应该能够请求数据和检索数据所需的任何格式
默认情况下,web api序列化为json对象。但是,如果将请求的内容类型设置为xml,则应返回相同的结果,但格式为xml而不是json。配置:
config.Formatters.Remove(config.Formatters.JsonFormatter);
config.Formatters.Insert(0, new CustomXmlMediaTypeFormatter());
自定义格式化程序:
public class CustomXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
public CustomXmlMediaTypeFormatter()
{
UseXmlSerializer = true;
}
}
这个看起来很管用,好吧,没那么优雅。
删除默认Xml格式化程序不起作用,
因此,我得出结论,框架仍在使用它。您的思路非常正确。但是您需要在config属性中初始化一个新的
XmlMediaTypeFormatter
实例,否则会影响全局引用
如您所知,您需要基于IControllerConfiguration
界面创建2个属性
public class Controller1ConfigAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings,
HttpControllerDescriptor controllerDescriptor)
{
var xmlFormater = new XmlMediaTypeFormatter {UseXmlSerializer = true};
controllerSettings.Formatters.Clear();
controllerSettings.Formatters.Add(xmlFormater);
}
}
public class Controller2ConfigAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings,
HttpControllerDescriptor controllerDescriptor)
{
var xmlFormater = new XmlMediaTypeFormatter();
controllerSettings.Formatters.Clear();
controllerSettings.Formatters.Add(xmlFormater);
}
}
然后用相关属性装饰控制器
[Controller1ConfigAttribute]
public class Controller1Controller : ApiController
{
[Controller2ConfigAttribute]
public class Controller2Controller : ApiController
{
Mark Jones的回答有一个很大的缺点:通过清除所有格式化程序,不可能请求不同的ContentType并使用相关的格式化程序
public class UseXMLSerializerAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
// Find default XMLFormatter
var xmlFormatter = controllerSettings.Formatters.FirstOrDefault(c => c.SupportedMediaTypes.Any(x => x.MediaType == "application/xml"));
if (xmlFormatter != null)
{
// Remove default formatter
controllerSettings.Formatters.Remove(xmlFormatter);
}
// Add new XMLFormatter which uses XmlSerializer
controllerSettings.Formatters.Add(new XmlMediaTypeFormatter { UseXmlSerializer = true });
}
}
为每个控制器启用XMLSerializer的更好方法是替换默认格式化程序
public class UseXMLSerializerAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
// Find default XMLFormatter
var xmlFormatter = controllerSettings.Formatters.FirstOrDefault(c => c.SupportedMediaTypes.Any(x => x.MediaType == "application/xml"));
if (xmlFormatter != null)
{
// Remove default formatter
controllerSettings.Formatters.Remove(xmlFormatter);
}
// Add new XMLFormatter which uses XmlSerializer
controllerSettings.Formatters.Add(new XmlMediaTypeFormatter { UseXmlSerializer = true });
}
}
然后像这样使用它:
[UseXMLSerializer]
public TestController : ApiController
{
//Actions
}
我尝试了您的解决方案,但格式化程序由控制器共享。我可以收到两个并发请求,每个控制器一个,这会造成UseXmlSerializer值不一致的问题。我只是不明白为什么这么难找到,我个人讨厌DataContractSerializer。