我有一个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
中读取它来在测试版中执行此操作,但已将其删除。
答案 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;
});
}
}