ASP.NET 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

我有一个带有2个控制器的自宿主Web API:

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。