【问题标题】:Creating MVC Delete button extension - How To Extend MVC's Html helper?创建 MVC 删除按钮扩展 - 如何扩展 MVC 的 Html 助手?
【发布时间】:2011-11-12 15:31:57
【问题描述】:

ASP.NET MVC 2 呈现一个链接(即<a>)来删除记录。

通过 GET 操作允许删除操作可能是有害的,所以我想通过发出 POST 来进行删除。

我创建了以下代码:

<% using (Html.BeginForm("Delete", "Boodschap", new { id = item.BoodschapID }))
    { %>
    <button>Delete</button>
<% } %>

现在我想将此代码作为扩展方法添加到 Html 助手中:

public static MvcForm DeleteButton(this HtmlHelper helper, string name, 
    string actionName, string controllerName, string routeValues)
{
    MvcForm form = helper.BeginForm(actionName, controllerName, routeValues);
    return form;
}

现在我被卡住了。如何让这个删除按钮起作用?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-2 html-helper


    【解决方案1】:

    如果您想生成完整的代码,那么让它返回MvcForm 是错误的。您希望它返回一个 MvcHtmlString 并在该方法中构造 HTML。这样您就可以将其用作:

    @Html.DeleteButton( "Delete", "Boodschap", new { id = item.BoodschapID } );
    

    直接生成 HTML(注意:未经测试,您可能需要合适的空值检查等)

    public static MvcHtmlString DeleteButton( this HtmlHelper helper, string name, 
        string actionName, object htmlAttributes )
    {
         return DeleteButton( helper, name, actionName, null, null, htmlAttributes );
    }
    
    public static MvcHtmlString DeleteButton( this HtmlHelper helper, string name, 
        string actionName, string controllerName, object routeValues, 
        object htmlAttributes )
    {
         var buttonBuilder = new TagBuilder("button");
         buttonBuilder.SetInnerText( name );
    
         var formBuilder = new TagBuilder("form");
         var urlHelper = new UrlHelper( helper.ViewContext.RequestContext );
         formBuilder.Attributes.Add( "action", urlHelper.Action( 
             actionName, controllerName, routeValues ) )
         formBuilder.Attributes.Add( "method", FormMethod.Post );
         formBuilder.MergeAttributes( new RouteValueDictionary( htmlAttributes ) );
         formBuilder.InnerHtml = buttonBuilder.ToString();
    
         return new MvcHtmlString( formBuilder.ToString() );
    }
    

    另一种方法是重用表单助手和 Response.Write,但让该方法返回一个(空)字符串,可能类似于:

    public static MvcHtmlString DeleteButton(this HtmlHelper helper, string name, string actionName, object routeValues)
    {
        return DeleteButton(helper, name, actionName, null, routeValues, null);
    }
    
    public static MvcHtmlString DeleteButton(this HtmlHelper helper, string name, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        using (helper.BeginForm(actionName, controllerName, routeValues, FormMethod.Post, htmlAttributes))
        {
            var response = helper.ViewContext.HttpContext.Response;
            var builder = new TagBuilder("button");
            builder.SetInnerText(name);
            response.Write(builder.ToString(TagRenderMode.Normal));
        }
        return MvcHtmlString.Create("");
    }
    

    【讨论】:

    • 我已经编辑了最后一个答案 - 经过一些更改 - 似乎可以正常工作。
    • 非常好的洞察如何在 HtmlHelper 中执行 response.Write。谢谢!!希望我能再次投票。
    【解决方案2】:

    虽然我认为 &lt;form&gt; 元素可以解决问题,但它不是很适合 AJAX。

    相反,为什么不将jQuerywire up to the click event 用于适当的&lt;a&gt; 链接,然后使用issue an HTTP POST to the server yourself

    $document.ready(function () {
        // "deleteLink is a class that identifies links that
        // are used for deleting, you might have some other mechanism
        $("a .deleteLink").click(function () { 
            $.post('post url', function(data) {
                // Do something with the data returned
            });    
        });
    });
    

    这样做的好处是,与为每个要删除的项目插入 &lt;form&gt; 相比,您可以使 HTML 更加更干净,并且与语义相关的干净标记总是比发展、SEO等方面。

    【讨论】:

    • 我喜欢使用某种 ajax 帖子的想法。更干净的 HTML 的论点在我脑海中挥之不去。我不知道这是否是商业应用程序的目标。自从我阅读hanselman.com/blog/… 以来,我一直想知道商业应用是否应该参与编写干净的 html。
    • @KeesC.Bakker:我不会说这是一个目标,但更干净的 HTML 是 IMO 良好开发实践的目标;当面对一堵 HTML 墙时,要翻遍这一切以查看哪里出了问题,这将是一场噩梦;使用 jQuery(或类似的东西),您可以更好地分离关注点;此外,您正在使用经过实战测试的代码。最后,当你们都遵循相同的范式而不是因为离题而试图自己找出利基案例时,会有更多的人在野外提供帮助。
    • 我赞成通过 AJAX 处理它,但如果页面上出现 javascript 错误或 javascript 被关闭,这将中断。您可以使用处理程序拦截表单提交并通过 AJAX 执行此操作 - 或者甚至打开表单,如果需要,只留下带有合适处理程序的按钮。
    • @tvanfosson:我同意由于页面上的 javascript 错误而破坏是有风险的,但是使用像 JSLint 和框架这样的工具,这种可能性变得越来越小。此外,如果页面上有许多这样的元素,那么“HTML 墙”将是一件痛苦的事情。使用 AJAX POST 也不是全新的东西……
    • @casperOne - 使用链接的问题是,如果出现问题,您会将删除操作公开为 GET。在客户端使用 javascript 展开表单并应用处理程序可以解决这两个问题。在为按钮构造处理程序时,您可以在表单上使用该操作,并且您永远不会为删除而公开锚标记。另一种选择是动态添加删除功能 - 在相关元素上使用 data 来构建路由 - 并且仅在您使用 javascript 时才可用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多