How to access the underlying object in SetDefaultC

2019-03-31 12:01发布

I have a web api where I return a object. When I use the accept header "image/jpg" i want the image representation of that object, but I want to set the file name based on the object I'm returning. I have implemented a BufferedMediaTypeFormatter and thought I should do this in the method SetDefaultContentHeaders like such:

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;
}

So the problem is how do I get the underlying object when I am in the SetDefaultContentHeaders? I was able to do it in the beta by reading it from the HttpResponseMessage that was passed in to the method, but that has been removed.

1条回答
爷的心禁止访问
2楼-- · 2019-03-31 12:07

You can't get the object instance there.

The only place in the formatter where you can access the object is the WriteToStreamAsync, and by that time you can't modify the headers anymore as they are already sent.

You have two options, either save the filename in the request.Properties in your controller and retrieve in the formatter by overriding GetPerRequestFormatterInstance (because it runs before SetDefaultContentHeaders). Then you can use this value in 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);
        }

Another is to use a delegating handler at the end of the pipeline: I.e. (of course you have filter out when you want to deserialize and so on):

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;
            });
        }
    }
查看更多
登录 后发表回答