ApiController 特定方法的自定义 MediaTypeFormatter (Serializer)

Custom MediaTypeFormatter (Serializer) for ApiController specific method

我有 ApiController 并且其中一种方法需要自定义序列化。

    public async Task<Session> PostSession([FromBody] Session session)

有大量 Session object 可以容纳所有东西,消费者不想得到超过一半,通常我可以用 [XmlIgnore()] 装饰属性并完成,然而,这个 object 正在通过许多 API 在内部传递,删除这些 API 会破坏这些机制。

另一种解决方案是将 object 替换为不同的 CastratedSession 和 return。我不能这样做,因为现有的第 3 方 API 正在调用相同的端点,这些 API 期望获得 Session,否则他们将不得不重写他们的东西(不会发生)。

然后我提议创建一个不同的端点,这个第 3 方可以调用 - 但架构师 objected 并说要根据特定的 content-type 值进行自定义 MediaTypeFormatter在 header 中设置,问题是我们已经在同一个控制器自定义 MediaTypeFormatter 中使用,而且我理解开箱即用的方式只能在每个控制器的配置中设置它们

public static void ConfigureApis(HttpConfiguration config)
{
    config.Formatters.Add(new CustomJsonFormatter()); 
    config.Formatters.Add(new CustomXmlFormatter()); 
}

哪一种把我逼到墙角。

如何(可以)在 ApiController 上为每个方法设置自定义 MediaTypeFormatter

您可以编写自定义操作过滤器,覆盖 OnActionExecuting 方法来检查目标操作,然后将适当的格式化程序添加到配置中。

internal class DecisionMakingFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var actionName= actionContext.ActionDescriptor.ActionName;
        if(actionName == "Some Foo")
        {
            actionContext.RequestContext.Configuration.Formatters.Add(new CustomMediaFormatter());
        }
        base.OnActionExecuting(actionContext);
        actionContext.RequestContext.Configuration.Formatters.Remove(new CustomMediaFormatter());
    }
}

我自己想出了一个解决方法

我继承并替换了 CustomXmlFormatter()EvenMoreCustomXmlFormatter()

然后在 WriteToStreamAsync 中这样做:

  public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        if (content.Headers.ContentType.MediaType == "text/sessionXml") // this was agreed with 3rd party
        {
            //do my serialization stuff
        }
        else
        {
            return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
        }
    }

希望这能为您节省一些时间。