从JsonMediaTypeFormatter扩展到设置客户标头不适用于http Accept标头

时间:2014-07-07 06:25:24

标签: c# asp.net asp.net-web-api mediatypeformatter

我的目标是为每个传出的JSON响应添加某些自定义标头。为此,创建了一个从SetDefaultContentHeaders JsonMediaTypeFormatter扩展的类,并覆盖了SetDefaultContentHeaders方法,如下所示:

public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    headers.Add("X-Answer", "42");
    headers.Add("X-Question", "Unknown");
}

然后我将我的派生媒体类型格式化程序添加到格式化程序列表中:

config.Formatters.Insert(0, new MyMediaTypeFormatter());

这个解决方案似乎适用于某些请求,但不适用于其他请求。经过一番调查,我发现如果我加入“接受”的话。请求中的标头,响应不包含我的自定义标头!这有点令人惊讶,因为响应类型仍然返回application / json,表明我的格式化程序或默认的json格式化程序正在处理响应。我唯一能想到的是调用SetDefaultContentHeaders的代码在 JsonMediaTypeFormatter中是,而SetDefaultContentHeaders不是虚拟的。

那么 - 这里发生了什么?什么是解决这个问题的最佳方法?

1 个答案:

答案 0 :(得分:2)

在我看来,媒体类型格式化程序只关注编码相关的标题。如果您要添加自定义标头,则应使用DelegatingHandlerActionFilter。您可以全局应用(将它们插入配置类中的相应集合中)和后续操作。使用DelegatingHandler的示例如下所示:

public class JsonHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage message, CancellationToken token)
    {
        var response = await base.SendAsync(message, token);
        IEnumerable<string> contentTypes;

        if(response.Headers.TryGetValues("Content-Type", out contentTypes)) 
        {
            // Check if there is an application/json Content-Type header
            // There should be 0 or 1, a call to FirstOrDefault() would be fine
            if(contentTypes.Any(ct => ct.Contains("application/json")))
            {
                response.Headers.Add("X-Answer", "42");
                response.Headers.Add("X-Question", "Unknown");
            }
        }

        return response;
    }
}

// And using HttpConfiguration configuration
configuration.MessageHandlers.Add(new JsonHeaderHandler());