表MVC中的ActionLink

时间:2014-11-13 14:21:38

标签: c# asp.net html5 razor asp.net-mvc-5

编辑:我已阅读并实施了this article中的方法,但这不起作用。

我有下表正确填充。

<table class="table">
   <tr>
       <th>Product</th>
       <th>File Name</th>
       <th>Release Date</th>
       <th>Size</th>
       <th></th>
   </tr>
   @{
       if (Model != null)
       {
           foreach (var item in Model.Uploads)
           {
               <tr>
                   <td>@Html.DisplayFor(modelItem => item.Product)</td>
                   <td>@Html.DisplayFor(modelItem => item.DisplayName)</td>
                   <td>@Html.DisplayFor(modelItem => item.ReleaseDate)</td>
                   <td>@Html.DisplayFor(modelItem => item.Size)</td>
                   <td>@Html.ActionLink("Delete File", "Upload", "Tools", new { id = item.DisplayName }, null)</td>
               </tr>
           }
       }
   }
</table>

我还有一个带有动作的控制器

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteUser(
    AdministratorViewModel model, string userName)
{
    // Do amazing stuff...
    return Index();
}

我想将选择删除的用户名传递给此操作。我认为我可以用@Html.ActionLink如上所述,但这不是要走的路。

如何将选定的用户名传递给我的操作方法?

感谢您的时间。


编辑:将Ajax代码更改为以下内容(使用Index作为被调用的方法)

@Ajax.ActionLink(
    "Remove",
    "Index", 
    "Tools",
    new
    {
        model = item,
        userName = item.UserName
    },
    new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        HttpMethod = "POST"
    })

并将DeleteUser(AdministratorViewModel model, string userName)方法的名称更改为Index(AdministratorViewModel model, string userName)。现在,这会触发Index中的ToolsController方法。但是调用的方法是NON-POST属性方法(!?)所以我现在有两个问题:

  1. 如何调用未标有[HttpPost]属性的方法?
  2. 为什么我可以使用Ben Griffiths&#39;来调用DeleteUser方法。回答如下?
  3. 如何在工具控制器中调用我的DeleteUser方法并传入模型和要删除的用户的名称?
  4. 感谢您的时间。

2 个答案:

答案 0 :(得分:5)

调用

时使用的ActionLink扩展方法重载的第四个参数
Html.ActionLink("Delete File", "Upload", "Tools", new { id = item.DisplayName }, null)

用于route values参数,您可以使用该参数将数据传回控制器。

目前,在上述调用中,Upload控制器上的Tools操作方法将接收id参数。如果要将显示名称传递回DeleteUser操作方法,可以使用

Html.ActionLink("Delete User", "DeleteUser", "[ControllerName]", new { userName = item.DisplayName }, null)

但是,DeleteUser方法使用HttpPost属性修饰,这意味着该操作只接受使用post方法的请求。这意味着您有三个选择:

(1)从动作方法中删除[HttpPost]属性 - 可能不是一个好主意,因为我想你不想暴露这个动作以获得有充分理由的请求。

(2)使用包含提交输入和隐藏的DisplayName输入而不是链接的表单。

(3)使用AjaxHelper.ActionLink扩展方法对控制器进行异步回发。 e.g:

Ajax.ActionLink("Delete User", "DeleteUser", "[ControllerName]", new { userName = item.DisplayName }, new AjaxOptions{ HttpMethod = "Post" })

更新:第三个选项的更完整示例

这是第三个选项的一个有效(尽管非常简单)的例子。我不是百分之百确定最终目标是什么,所以不是试图提供一个现实的例子,我试图创造一个简单但清晰的例子。请注意,我已经省略了防伪标记的处理以帮助澄清,但我坚持采用async动作方法,以免偏离现实生活。

控制器:

public class HomeController : Controller {

    private async Task<string> Delete(string displayName) {
        Thread.Sleep(1000);
        return string.Format("{0} has been deleted", displayName);
    }

    [HttpPost]
    [AllowAnonymous]
    public async Task<JsonResult> DeleteItem(string displayName, int product) {

        Task<string> deleteTask = Delete(displayName);

        return new JsonResult() {
            Data = new { 
                product = product,
                result = await deleteTask }
        };
    }



    public ActionResult Index() {

        AdministratorViewModel model = new AdministratorViewModel() {
            Uploads = new List<ItemModel>() {
                new ItemModel() {
                    DisplayName = "First one",
                    Product = 1,
                    ReleaseDate = DateTime.Now,
                    Size = 11
                },
                new ItemModel() {
                    DisplayName = "Second one",
                    Product = 2,
                    ReleaseDate = DateTime.Now.AddDays(1),
                    Size = 12
                }
            }
        };


        return View(model);
    }

}

型号:

public class AdministratorViewModel {
    public IEnumerable<ItemModel> Uploads { get; set; }
}

布局:

<!DOCTYPE html>
<html>
    <head>
        <title>Demo</title>
    </head>
    <body>
        @RenderBody()
        <script src="~/Scripts/jquery-1.10.2.js"></script>
        <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
        @RenderSection("scripts", false)
    </body>
</html>

主页/索引视图:

 @model AdministratorViewModel

 <table class="table">
    <tr>
        <th>Product</th>
        <th>File Name</th>
        <th>Release Date</th>
        <th>Size</th>
        <th></th>
    </tr>
    @{
        if (Model != null) {
            foreach (var item in Model.Uploads) {
                <tr>
                    <td>@Html.DisplayFor(modelItem => item.Product)</td>
                    <td>@Html.DisplayFor(modelItem => item.DisplayName)</td>
                    <td>@Html.DisplayFor(modelItem => item.ReleaseDate)</td>
                    <td>@Html.DisplayFor(modelItem => item.Size)</td>
                    <td>@Ajax.ActionLink("Remove", "DeleteItem", "Home", new { displayName = item.DisplayName, product = item.Product }, new AjaxOptions { HttpMethod = "POST", OnComplete = "itemDeleted" }, new { id = item.Product })</td>
                </tr>
            }
        }
    }
</table>

@section scripts {
    <script>
        var itemDeleted = function (data) {
            var $link = $('#' + data.responseJSON.product);
            $link.parents('tr')
                 .children()
                 .css('text-decoration', 'line-through');

            $link.remove();

            alert(data.responseJSON.result);
        };
    </script>
}

答案 1 :(得分:1)

我认为首先你要通过添加像

这样的路由来处理网址
routes.MapRoute(
                name: "Default",
                url: "{User}/{DeleteUser}/{username}",
                defaults: new { controller = "Home", action = "Index", username = UrlParameter.Optional }
            );