从Asp Net Web API Controller

时间:2015-06-07 15:26:55

标签: ajax excel knockout.js asp.net-web-api steam-web-api

我正在研究使用Web API作为业务层的新Web应用程序,并将Js作为客户端框架工作来敲除绑定。我有一个要求,例如将某些搜索条件传递给Web API控制器,并从数据库中获取数据,并将动态创建和发送Excel / MS-Word文件作为可下载内容。

我是Web API和Knock的新手,我正在网上搜索并获得部分解决方案,我正在寻找这个用例的更优化解决方案。

以下是我的代码:

客户端:

 function GetExcelFile() {
    var $downloadForm = $("<form method='POST'>")
      .attr("action", baseUrl + "api/FileHandler/GetExcelFileTest")
              .attr("target", "_blank")
    $("body").append($downloadForm);
    $downloadForm.submit();
    $downloadForm.remove();
}

On按钮单击此代码片段即可动态创建表单并从Web API获取响应。

Web API代码:

[HttpPost]
        public HttpResponseMessage GetExcelFileTest()
        {
            var response = new HttpResponseMessage();
            //Create the file in Web App Physical Folder
            string fileName = Guid.NewGuid().ToString() + ".xls";
            string filePath = HttpContext.Current.Server.MapPath(String.Format("~/FileDownload/{0}", fileName));

            StringBuilder fileContent = new StringBuilder();
            //Get Data here
            DataTable dt = GetData();
            if (dt != null)
            {
                string str = string.Empty;
                foreach (DataColumn dtcol in dt.Columns)
                {
                    fileContent.Append(str + dtcol.ColumnName);
                    str = "\t";
                }
                fileContent.Append("\n");
                foreach (DataRow dr in dt.Rows)
                {
                    str = "";
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        fileContent.Append(str + Convert.ToString(dr[j]));
                        str = "\t";
                    }
                    fileContent.Append("\n");
                }
            }
            // write the data into Excel file
            using (StreamWriter sw = new StreamWriter(fileName.ToString(), false))
            {
                sw.Write(fileContent.ToString());
            }
            IFileProvider FileProvider = new FileProvider();
            //Get the File Stream
            FileStream fileStream = FileProvider.Open(filePath);
            //Set response
            response.Content = new StreamContent(fileStream);
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = fileName;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/ms-excel");
            response.Content.Headers.ContentLength = fileStream.Length;
            //Delete the file

            //if(File.Exists(filePath))
            //{
            //    File.Delete(filePath);
            //}
            return response;
        }

使用此代码,我可以下载Excel文件。我还有一些更开放的问题可以使这段代码变得最佳。

Q1)我需要将视图模型(搜索条件)传递给API控制器使用动态创建表单? (或)从Web API获取Excel文件的更好方法。

Q2)我确信这不是在Physical文件夹和Get FileStream中创建Excel文件并作为respone发送的好方法。如何做到飞行?或任何其他最佳方式。

请建议我做更好的方法..谢谢

1 个答案:

答案 0 :(得分:0)

Q1)你可以很容易地传递视图模型,但同样也很容易从发布的表单中提取信息。

传递视图模型

如果要将视图模型传递给WebAPI方法,请记住所述方法必须将具有相同属性的对象作为参数。因此,如果您希望回发的对象始终具有相同的属性,那么构建具有相同属性的服务器端类并接收该类的实例是微不足道的。

要回发这个客户端对象,你可以做这样的事情(使用jQuery,我看到你已经使用过了):

$.ajax({
    contentType: "application/json",
    data: my-view-model.toJSON(),
    type: "POST",
    url: baseUrl + "api/FileHandler/GetExcelFileTest" });

我还没有附加任何successerror处理程序,因为JavaScript并不关心返回,但您可能希望添加一些处理程序以防异常抛出WebAPI方法。我建议您通过在上述$.ajax()电话中添加以下内容来实现此目的:

statusCode: {
    500: function(jqXhr, textStatus, errorThrown) {
    },
    [other HTTP error codes]
}

[阅读$.ajax()来电here的文档。]

此处还有一个提示:当您调用my-view-model.toJSON()(或self.toJSON()时,如果在视图模型中调用),Knockout将首先确定您的视图模型是否包含{{1} } 方法。如果是这样,它将使用此方法;如果没有,那么它将调用浏览器的这个功能的实现。但是,浏览器对此函数的实现将序列化所有内容,例如,如果您具有视图模型中的长选择列表,则可能会特别长。因此,如果您只希望发回视图模型属性的子集,请在视图模型上定义自己的toJSON()函数,如下所示:

toJSON

[了解有关将视图模型转换为JSON here的详情。]

按原样发布表单

如果您不想花费精力进行视图模型布线,那么您可以像在问题中一样发布表单。然后,您可以使用

从表单中检索值
var toJSON = function() {
    return {
        Property1: ...,
        Property2: ...
    };
}

Q2)

您可能正确地指出在物理文件夹中创建Excel文件并不明智。但是,据我所知(如果有人另有说法,感兴趣),你必须使用第三方库。 Microsoft确实提供Office自动化库,但我怀疑您还需要在同一位置安装Office。

动态创建Excel电子表格是我已经多次完成的事情,但对于实际创建我使用Aspose.Cells,这需要许可证。虽然我创建一个物理版本然后将其删除,但我相信Aspose.Cells可能允许您将其创建为流。但是看一看,肯定有其他库提供Excel自动化。

从服务器返回文件

单独拨打Request.Form["my-field"]; 不会让您向用户显示&#34;另存为...&#34;对话。在这种情况下我做了什么 - 如果您希望仅将生成的文件存储在内存中(例如FileStream)而不是文件系统上,那么这将无法正常工作 - 是响应$.ajax({...})调用使用生成文件的文件名。

下一步是引导用户使用该文件名。

所以我在JavaScript中有这样的东西:

$.ajax({...})

但不要对这种重定向感到震惊。 $.ajax({ dataType: "json", type: "GET", // you'll probably want POST in your case url: ..., success: function(response) { if (response && response.Uri && response.Uri.length) { window.location.href = [root URL] + response.Uri; } } }); 直接指向服务器上的文件夹,不需要控制器。因为浏览器然后接收一个文件,它会显示&#34;另存为...&#34;保留在同一网页上的对话框。