ASP.NET MVC通过模态弹出窗口下载csv文件

时间:2018-04-04 17:38:20

标签: c# jquery ajax asp.net-mvc razor

我试图通过asp.net mvc控制器下载csv文件,但由于我需要用户通过下拉列表进行选择输入,我创建了一个bootstrap模式弹出窗口。

@using (Html.BeginForm("Create", "Home", FormMethod.Post, new { @class = "modal-form" }))
{
    <div class="modal-body">
        <div class="form-horizontal">
            <div class="form-group">
                @Html.Label("locationTypeId", new { @class = "control-label col-md-3" })
                <div class="col-md-4">
                    @Html.DropDownList("locationTypeId", Model.LocationList, new { @class = "form-control" })
                </div>
            </div>
        </div>
    </div>

    <div class="modal-footer">
        <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
        <button class="btn btn-primary" type="submit">Save</button>
    </div>
}

一旦用户点击“保存”按钮,它就会发送到控制器:

[HttpPost]
public ActionResult Create(DefaultViewModel model)
{
    if (ModelState.IsValid)
    {
        try
        {
            var repository = new SqlRepository(model);
            // go about creating csv file

            // returns byte[]
            var output = repository.CreateShipmentDataUpload();

            //DownloadCSV();
            return Json(new { success = true });
        }
        catch (Exception e)
        {
            ModelState.AddModelError("", e.Message);
        }
    }

    return PartialView("_Create", model);
}

我不确定我是否可以/应该在那里调用DownloadCSV()。这是DownloadCSV():

public FileContentResult DownloadCSV(byte[] byteArray)
{
    return File(byteArray, "text/csv", "report.csv");
}

这里是ajax成功函数调用:

@section Scripts {
<script type="text/javascript">

    function bindForm(dialog) {
        $('form', dialog).submit(function () {
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.success) {
                        $('#modalDialog').modal('hide');
                        // Refresh:
                        location.reload();
                    } else {
                        $('#modalContent').html(result);
                        bindForm();
                    }
                }
            });
            return false;
        });
    }
</script>
}

如何下​​载csv文件才能正常工作?

2 个答案:

答案 0 :(得分:1)

  1. 从模式弹出窗口中取出窗体控件

  2. 让你的模态提交按钮调用js脚本来关闭模态并激活ajax回调在控制器上下载CSV方法传递他们在模态下拉列表中做出的选择(通过获取元素的val来获取他们的选择ID

  3. 在下载CSV方法

  4. 中执行字节解析逻辑和返回文件

    关于模态弹出窗口的重要思想就是不要通过页面重新加载来杀死你的用户。你已经完成了模式弹出和ajax调用的所有艰苦工作,然后你最后解决了页面加载问题。这就像参加比赛,然后坐在终点线前5英尺处。

    实施例

    要在下拉列表中显示的测试类:

    public class Whatever
    {
        public int locationTypeId { get; set; }
        public List<SelectListItem> Locations { get; set; }
    }
    

    控制器方法:

        public ActionResult Wut()
        {
            Whatever wut = new Whatever();
            wut.Locations = new List<SelectListItem>();
            wut.Locations.Add(new SelectListItem { Text = "Uno", Value = "1" });
            wut.Locations.Add(new SelectListItem { Text = "Dos", Value = "2" });
            return View(wut);
        }
        public FileContentResult DownloadCSV(string location)
        {
            return File(new System.Text.UTF8Encoding().GetBytes("Generate, CSV, LOGIC, HERE, DEPENDING, ON, LOCATION"), "text/csv", "Example" + DateTime.Now.ToString("_MM-dd-yyyy-mm-ss-tt") + ".csv");
        }
    

    查看:

        @model DeleteMeWeb.Controllers.Whatever
        <div class="btn btn-primary" id="showModal">Show Modal</div>
    
        <div class="modal" tabindex="-1" role="dialog" id='myModal'>
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Modal title</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        @Html.DropDownList("locationTypeId", Model.Locations, new { @class = "form-control" })
                    </div>
                    <div class="modal-footer">
                        <div class="btn btn-primary" id="fire">Save changes</div>
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>
    

    JS:

        @section scripts
        {
            <script>
                $('#myModal').modal('hide');
                $('#showModal').click(function () { $('#myModal').modal('show'); });
                $('#fire').click(function (){
                    $('#myModal').modal('hide');
                    //FIRE GET REQUEST WHEN RETURNING A FILE IT WILL FORCE DOWNLOAD WITHOUT PAGE NAVIAGTION
                    window.location = "/Home/DownloadCSV?location=" + $('#locationTypeId').val();
                });
            </script>
        }
    

答案 1 :(得分:0)

您无法使用相同的Json来回复FileContentResult个回复和Ajax。你可以: -

  1. 发送$ .ajax请求以执行表单验证(在创建要下载的文件之前),如果验证正常($ .ajax成功),则发送另一个“fire and forget”请求以创建并使用原始FileContentResult函数中的$.ajax success操作下载表单。或

  2. 如果验证失败,只需发送“fire and forget”并返回空文件(或无文件)。

  3. 两种方案都允许您以受控方式关闭模式而无需重新加载页面; FileContentResult只需下载文件而不影响视图。

    实现“火与忘”的一种方法是:

    var data = { id: "someId" };
    var form = document.createElement("form");
    form.setAttribute("method", "GET");
    form.setAttribute("action", "url/to/DownloadCSV");
    if (data != null && data.constructor === Object) {
        for (var key in data) {
            if (data.hasOwnProperty(key)) {
                var hiddenField = document.createElement("input");
                hiddenField.setAttribute("type", "hidden");
                hiddenField.setAttribute("name", key);
                hiddenField.setAttribute("value", data[key]);
                form.appendChild(hiddenField);
            }
        }
    }
    document.body.appendChild(form);
    form.submit();
    form.remove();
    

    这将在$ .ajax请求的if (result.success) { }部分中进行(或被引用)(如果您打算验证),以及$('#modalDialog').modal('hide');(但不是location.reload();)< / p>

    文件下载操作将类似于:

    public FileContentResult DownloadCSV(string someParameterToMakeTheFileIfNeeded)
    {
        // Make the file and then return the FileContentResult here
        return File(byteArray, "text/csv", "report.csv");
    }
    

    有很多方法可以让这只猫受到伤害,值得研究一下那里的东西,但我觉得这对我很有用。