Asp.net Web API - 如何设置自定义CSV媒体类型格式化程序的文件名

Luk*_*ins 11 .net asp.net-web-api

我已经在ASP.Net Web API项目中成功实现了Csv Media Type Formatter.我能够以Csv格式获得结果.但是,生成的文件名是没有扩展名的"部分".

理想情况下,我希望能够在控制器中设置此文件名,但能够全局添加扩展名是最小的.

以下是我找到的例子

覆盖OnGetResponseHeaders - 我不认为这是当前版本中的一个选项. http://forums.asp.net/t/1782973.aspx/1?Setting+response+and+content+headers+esp+ContentDisposition+inside+a+MediaTypeFormatter

根据那篇文章,这应该有效

public override IEnumerable<KeyValuePair<string, string>> OnGetResponseHeaders(Type objectType, string mediaType, HttpResponseMessage responseMessage)
{
       return new[] { new KeyValuePair<string, string>("Content-Disposition", "attachment; filename=testing.csv") };
}
Run Code Online (Sandbox Code Playgroud)

但是Visual Studio说"没有合适的覆盖方法",并且在我将其添加到自定义Csv Formatter时不会编译.

从控制器返回HttpMessageResponse - 如何在ASP.NET Web API中设置下载文件名 但是这似乎只是推送现有的服务器文件,这将使Csv序列化无法进行.以下是尝试使此方法工作:

public HttpResponseMessage Get(string id)
{
    var response = new HttpResponseMessage();

    if (id == "test")
    {
        var data = GetTestData();
        response.StatusCode = HttpStatusCode.OK;
        response.Content = new StreamContent(data);
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = "testorama.csv";
        return response;
    }

    return null;
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是新的StreamContent()期待一个流 - 有没有办法获得Custom Csv Formatter创建的当前流?

最重要的是,如何为首先序列化为Csv格式的结果集设置文件名?

解

谢谢克劳迪奥 - 让我朝着正确的方向前进.一对夫妇与你发布的内容有所不同:

  1. 我从我的自定义Csv Formatter派生出BufferedMediaTypeFormatter,并使用SetDefaultContentHeaders而不是从MediaTypeFormatter派生.

  2. SetDefaultContentHeaders接受mediaType参数,其类型为MediaTypeHeaderValue而不是string.

这是最终的代码:

public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    headers.Add("Content-Disposition", "attachment; filename=testorama.csv");
}
Run Code Online (Sandbox Code Playgroud)

Cla*_*edi 14

覆盖SetDefaultContentHeadersMediaTypeFormatter上的方法

public override void SetDefaultContentHeaders(
    Type type, HttpContentHeaders headers, string mediaType)
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    headers.Add("Content-Disposition", "attachment; filename=yourname.csv");
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 7

为了根据数据提供自定义名称(至少在Web API 2中),您需要覆盖GetPerRequestFormatterInstance.从那里,您可以访问HttpRequestMessage.

private string FileName { get; set; }

public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    if (!string.IsNullOrEmpty(FileName))
        headers.Add("Content-Disposition", string.Format("attachment; filename={0}", FileName));
}

public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
    // We aren't setting the name, so just return the current instance.
    if (!request.Properties.ContainsKey("filename")) return this;

    var formatter = new CsvFormatter();
    var fileName = request.Properties["filename"] as string;
    formatter.FileName = string.Format("{0}.csv", fileName);
    return formatter;
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的控制器操作中,您可以像这样设置文件名...

if (!Request.Properties.ContainsKey("filename"))
    Request.Properties.Add("filename", "MyFile.{ext}");
Run Code Online (Sandbox Code Playgroud)

我使用{ext}以防我添加需要文件名的其他格式化程序.理论上,只需要更改扩展名以支持其他格式.