将文件名传递给视图

时间:2016-09-03 10:55:06

标签: c# asp.net-mvc file-management

我正在尝试构建一个简单的CMS,允许作者上传文件(特别是图片,但文件类型现在并不重要)。

上传文件工作正常。但是,我想提供列出并随后删除文件的功能(可能是以后的多个文件,但现在一次只能保存一个文件)。

我环顾四周。我看到很多使用EF将文件的位置存储在数据库中的例子,因为它们具有权限和角色等等。虽然这是我将来可能需要解决的问题,但它不是一个复杂的层,我愿意添加正确的现在

我只想按一下删除链接(就像删除数据库中的记录一样)。触发调用删除确认视图的操作。然后在该视图上,删除按钮以实际删除文件并将用户返回到列表。以下是我目前的代码:

这将是列出文件的视图:

@model IEnumerable<FileInfo>

@{
    ViewBag.Title = "File List";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Upload", "Upload")
</p>
<table class="table">
    <tr>
        <th>File Name</th>
        <th>Actions</th>
    </tr>

    @foreach (FileInfo file in Model)
    {
        <tr>
            <td>@file.Name</td>
            <td>@Html.ActionLink("Delete", "Delete", new { fileName = @file.Name })</td>
        </tr>
    }
</table>

我不会为这个视图显示控制器,因为它相对简单,而不是我遇到问题的地方(我认为)。我只是展示了这个,所以你可以看到删除链接并告诉我是否有任何错误。

以下是删除确认视图:

@model FileInfo

@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>

<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.FullName)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.FullName)
    </dd>
</dl>
@using (Html.BeginForm("Delete", "FileManagement", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

    <div class="form-actions no-color">
        @Html.ActionLink("Back to list of views", "Index", null, new { @class = "btn btn-success" })
        &nbsp;|&nbsp;
        @*@Html.ActionLink("Delete", "Delete", null, new { @class = "btn btn-danger" })*@
        <input type="submit" value="Delete file" formaction="Delete" formmethod="delete" class="btn btn-danger" />
    </div>
}

以下是两个删除操作(GET和POST / DELETE)

    // GET: FileManagement/Delete/filename
    public ActionResult Delete()
    {
        return View();
    }

    // POST: FileManagement/Delete/filename
    [HttpDelete]
    [ValidateAntiForgeryToken]
    public ActionResult Delete(string fileName)
    {
        var path = Path.Combine(Server.MapPath("~/UserFiles"), fileName);

        if (System.IO.File.Exists(path))
            System.IO.File.Delete(path);
        else
            return HttpNotFound();

        return RedirectToAction("Index");
    }

我没有查看模型,因为我还没有连接到数据库。这些文件只是上传到文件夹〜/ UserFiles / someFileName.ext,并且通过正常方式将此文件附加到server.mappath来获取完整路径。

我遇到的问题是将文件名放入删除确认视图,并进入删除按钮,将其传递给删除操作以完成工作。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在主视图中(我假设Index.cshtml),您正确生成fileName的查询字符串值,但GET方法没有接受它的参数。它需要

// GET: FileManagement/Delete/filename
public ActionResult Delete(string fileName)

并且在该方法中,您需要基于FileInfo初始化新的fileName类,并将该模型传递给视图。

下一个问题是您的确认页面中的表单没有将文件名传递回POST方法,但这引发了另一个问题,即您不能使用具有相同签名的GET和POST方法,因此您需要更改其中一个方法的名称,例如

[HttpGet]
public ActionResult ConfirmDelete(string fileName)

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(string fileName)

并在确认删除页面中,将表单更改为

@using (Html.BeginForm("Delete", "FileManagement", new { fileName = Model.Name })) // enctype not required
{
    @Html.AntiForgeryToken()
    <input type="submit" value="Delete file" class="btn btn-danger" />
}

但是,您可以通过在Index视图中生成表单并显示确认对话框(不再需要GET方法)来大大提高性能。

@foreach (FileInfo file in Model)
{
    ....
    @using(Html.BeginForm("Delete", "FileManagement", new { fileName = file.Name }))
    {
        @Html.AntiForgeryToken()
        <input type="submit" value="delete" />
    }
}

并添加脚本以显示对话框

$('form').submit(function() {
    return conform("Are your sure .... ");
});

将显示浏览器的javascript确认对话框。您可以通过在确认对话框中使用jquery插件来进一步增强UI(或实现您自己的,如this article中所述)

您还应该考虑使用ajax来提交表单(并在成功回调中,删除按钮及其关联的表行)。典型的实现可能看起来像

@foreach (FileInfo file in Model)
{
    <tr>
        <td>@file.Name</td>
        <td>
            <form class="deleteform">
                @Html.AntiForgeryToken()
                <input type="hidden" name="fileName" value="@file.Name" />
                <input type="submit" value="delete" />
            </form>
        </td>
    </tr>
}

var url = '@Url.Action("Delete", "FileManagement")';
$('.deleteform').submit(function() {
    var formData = $(this).serialize();
    var row = $(this).closest('tr');
    $.post(url, formData, function(response) {
        if (response) {
            row.remove();
        } else {
            // Oops - display message?
        }
    }).fail(function (response) {
        // Oops
    });
    return false; // cancel the default submit
});

和控制器方法

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(string fileName)
{
    .... // delete the file
    return Json(true); // indicate success
    // or return Json(null); to indicate failure
}