将文件名传递给视图

Passing a filename to a view

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

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

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

我只想简单地按下删除键 link(就像您要删除数据库中的记录一样)。触发调用删除确认视图的操作。然后在那个视图上,一个删除按钮实际删除文件和 return 用户到列表。以下是我目前的代码:

这将是列出文件的视图:

@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>

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

下面是删除确认视图:

@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 获得的。

我遇到的问题是将文件名输入到删除确认视图中,并将文件名输入到删除按钮中,后者会将其传递给删除操作以完成这项工作。

感谢您的帮助。

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

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

并且在该方法中,您需要根据 fileName 初始化一个新的 FileInfo class 并将该模型传递给视图。

下一个问题是您在确认页面中的表单没有将文件名传递回 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 提交表单(并在成功回调中删除按钮及其关联的 table 行)。一个典型的实现可能看起来像

@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
}