使用ASP.NET Web Api导出文件下载

时间:2012-09-05 16:17:55

标签: c# jquery ajax asp.net-mvc-4 asp.net-web-api

我将CSV导出添加到使用ASP.NET Web API实现的服务。

目前我有一个视图模型(包含结果过滤的详细信息),它通过ajax POST请求发送到Web API控制器。然后在UI上呈现JSON响应。这很好用。

现在我想将相同的视图模型发布到另一个控制器,让我们将它命名为ExportController。然后我需要将文件下载给用户。

我的想法:

  1. 将视图模型发布到服务,将其存储在持久存储(DB或内存缓存,无关紧要)的某处,并将导出令牌返回给用户。 (通过导出令牌,我指的是用于标识此特定导出的一条信息)

  2. 然后在网址中使用该令牌从GET执行iframe请求 并获取该文件作为对此请求的响应。

  3. 我现在所拥有的,在用户界面上:

    var exportUrl = "URL to ExportController"
    $.ajax(exportUrl, {
       type: 'POST',
       contentType: 'application/json',
       data: postData
    })
    .success(function(data) {
        // this should download the file
        $('#export').attr('src', exportUrl + '&exportToken=' + data);
    });
    

    这里' #export'是用于下载文件的iframe元素。

    这是导出后端的原始草图:

    public class ExportController : ApiController
    {
        ...
    
        // GET /api/Export
        public string Get(string exportToken)
        {
            // get filters from DB
            var filters = ExportArgumentProvider.GetFilters(exportToken);
    
            // get data
            var result = DataSource.GetData(filters);
    
            return result;
        }
    
        // POST /api/Export
        public string Post(FilterInput filters)
        {
            var guid = Guid.NewGuid();
    
            // save filters to DB
            ExportArgumentProvider.AddFilter(guid, filters);
    
            return guid.ToString();
        }
    }
    

    这个伪代码显然不起作用,请忽略Get方法的返回类型。

    所以,问题:

    1. 是否有更简单的方法进行此导出(不在DB中存储过滤器状态)。
    2. 这种方法是否合理(状态存储在DB等中),还是应该以其他方式完成此类任务?
    3. ASP.NET Web API是否适合此类任务,或者我应该使用通常的ASP.NET控制器进行导出?
    4. 更新:发布到服务器的数据可能会超出URL长度限制,因此通过GET请求传递数据实际上不是一种选择。

2 个答案:

答案 0 :(得分:0)

我建议只将两个请求组合成一个:使“导出”URL获取所有参数都是“即时”导出。有一个小的限制,你只能在查询字符串中填充如此多的数据,所以这可能不适合你,但我建议你去做(因为它会简化问题)。

假设“postData”(在组件的第一部分中)“足够小”,那么您只需将其序列化为“导出”URL的查询字符串,然后将端点组合在一起(以便导出URL处理数据/等的过滤。)

答案 1 :(得分:0)

对于这个项目,我放弃了创建干净和RESTful后端并将ExportController转换为通常的MVC控制器。然后我可以在Post方法

中更改此行
ExportArgumentProvider.AddFilter(guid, filters);

进入

Session[exportId] = filters;

并使用Get方法执行相同的操作。

我仍然认为在DB中存储过滤器的方法要好得多,但是

  1. 我不需要REST API。
  2. 它在代码中引入了太多的开销,远远超过我想添加的“仅仅为了API的纯度”。