如何在SetDefaultContentHeaders中访问底层对象?

时间:2012-09-24 10:55:31

标签: asp.net-web-api

我有一个web api,我返回一个对象。当我使用接受标题“image / jpg”时,我想要该对象的图像表示,但我想根据我正在返回的对象设置文件名。我已经实现了BufferedMediaTypeFormatter并认为我应该在方法SetDefaultContentHeaders中执行此操作,如下所示:

public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    var myObject = // How do I get this from the response?
    var contentDispositionHeader = new ContentDispositionHeaderValue("attachment") 
        { FileName = myObject.FileName };
    headers.ContentDisposition = contentDispositionHeader;
}

所以问题是当我在SetDefaultContentHeaders时如何获得底层对象?我可以通过从传递给方法的HttpResponseMessage中读取它来在测试版中执行此操作,但已将其删除。

1 个答案:

答案 0 :(得分:7)

你无法在那里获得对象实例。

格式化程序中唯一可以访问对象的地方是WriteToStreamAsync,到那时你就不能再修改标题了,因为它们已经被发送了。

您有两个选项,可以将文件名保存在控制器的request.Properties中,并通过覆盖GetPerRequestFormatterInstance(因为它在SetDefaultContentHeaders之前运行)在格式化程序中检索。然后,您可以在SetDefaultContentHeaders

中使用此值
//Controller
public Url Get(int id)
        {
            Request.Properties.Add("name", _repo.Get(id).Name);
            return _repo.Get(id);
}

//Formatter
        public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType)
        {
            //here save the request.Properties["name"] to some local field which you can use later
            return base.GetPerRequestFormatterInstance(type, request, mediaType);
        }

另一种方法是在管道的末尾使用委托处理程序: 即(当然你想要反序列化时过滤掉等等):

public class RenameHandler : DelegatingHandler
    {
        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
            {
                var msg = t.Result;
                var myobj = msg.Content.ReadAsAsync<IMobi>().Result;
                msg.Content.Headers.ContentDisposition.FileName = myobj.Name + ".mobi";

                return msg;
            });
        }
    }