ASP.Net 如何在不重定向视图的情况下调用控制器中的方法

ASP.Net how to call a method in a controller without redirecting the view

我有一个视图显示指定文件夹中的每个文件,名称旁边有一个删除按钮。我希望用户能够单击按钮,从文件夹中删除文件,然后使用更新的文件列表刷新页面。

Index.cshtml


@{
    ViewBag.Title = "Index";
}

@{
    var arrayOfDocs = ViewData["arrayOfDocs"] as string[];
}

<h2>Case Log Documents</h2>

<table class="table">
    <tr>
        <th>
            Files
        </th>
        <th></th>
    </tr>

    @foreach (var item in arrayOfDocs)
    {
<tr>
    <td>
        <a href="~/Case_Log_Docs/@item">@item</a>
    </td>
    <td>
        @Html.ActionLink("Delete", "Delete", new { fileName = item })
    </td>
</tr>
    }

</table>

通过这一行,我试图在我的控制器中调用 Delete 方法 @Html.ActionLink("Delete", "Delete", new { fileName = item })。但是 link 操作将我重定向到删除页面(该页面不存在,也永远不会存在)。我想要发生的是调用 'Delete' 方法,然后刷新我所在的页面。

控制器

   [HttpPost]
        public ActionResult Delete(string fileName)
        {
            try
            {
                string path = Server.MapPath("~/Case_Log_Docs/");
                string fullPath = path + fileName;
                if (System.IO.File.Exists(fullPath))
                {
                    System.IO.File.Delete(fullPath);
                }

                return RedirectToAction("Index");
            }
            catch
            {
                return View("Index");
            }
        }

我该如何设置才能做到这一点?

我觉得好像找不到路线。你有几件事要做。

首先,您已将您的方法标记为接受带有 POST 动词的 Http 请求:

[HttpPost]
public ActionResult Delete(string fileName)

这意味着来自前端的请求需要使用 POST 作为动词才能被适当地路由。正如@jackdraw 在他的回答中提到的那样,您需要使用一个表单来完成此操作。或者,您可以执行 Ajax post 但该选项似乎超出了您的问题范围,因此请将 table 包含在表单标签中。您还没有提供控制器的名称,所以我将使用占位符:

@using (Html.BeginForm("Delete", "NameOfControllerWithDeleteMethod"))
{
    //Put your table here
}

您还需要一个字段来保存您要删除的内容的标识符。在这种情况下,文件名本身:

@using (Html.BeginForm("Delete", "NameOfControllerWithDeleteMethod"))
{
    <input type="hidden" id="fileName" name="fileName" />
    //Put your table here
}

然后您需要在该字段中填写您要删除的文件的名称。您可以在删除按钮的 Click 事件上执行此操作。将您的操作 link 替换为类型 submit 的输入并使用 JS 进行设置。在你的循环中。注意JS字符串和Razor代码的插值:

@foreach (var item in arrayOfDocs)
{
<tr>
<td>
    <a href="~/Case_Log_Docs/@item">@item</a>
</td>
<td>
    <input type="submit" value="Delete File" onclick="document.getElementById('fileName').value = '@item';" />
</td>
</tr>
}

最后,在您的控制器的 Delete 方法中,无论是否遇到错误,您都希望在这两种情况下都重定向回原始 Index 方法。您可以使用临时数据收集传回只显示一次的消息:

try
{
    string path = Server.MapPath("~/Case_Log_Docs/");
    string fullPath = path + fileName;
    if (System.IO.File.Exists(fullPath))
    {
        System.IO.File.Delete(fullPath);
    }

    TempData["UserMessage"] = "Success!";
    return RedirectToAction("Index", "NameOfControllerWithIndexMethod");
}
catch
{
    TempData["UserMessage"] = "Something went wrong... :-(";
    return RedirectToAction("NameOfControllerWithIndexMethod");
}

在您的视图中收集此数据并将其显示在某处:

@{ var userMessage = TempData["UserMessage"] as string; }
@if(!string.IsNullOrWhiteSpace(userMessage))
{
    <div class="some-message-style">@userMessage</div>
}