是否有一些简单的方法来处理来自同一个表单的多个提交按钮?例如:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>

知道如何在ASP中做到这一点吗?NET框架测试版?我在谷歌上搜索的所有例子中都有单个按钮。


当前回答

我没有足够的代表在正确的地方发表评论,但我花了一整天的时间在这上面,所以想分享。

在尝试实现“MultipleButtonAttribute”解决方案时,ValueProvider.GetValue(keyValue)将错误地返回null。

原来我引用的是System.Web.MVC版本3.0,而它应该是4.0(其他程序集是4.0)。我不知道为什么我的项目没有正确升级,我没有其他明显的问题。

所以如果你的ActionNameSelectorAttribute不工作…检查。

其他回答

以下是最适合我的方法:

<input type="submit" value="Delete" name="onDelete" />
<input type="submit" value="Save" name="onSave" />


public ActionResult Practice(MyModel model, string onSave, string onDelete)
{
    if (onDelete != null)
    {
        // Delete the object
        ...
        return EmptyResult();
    }

    // Save the object
    ...
    return EmptyResult();
}

视图中的代码是:

<script language="javascript" type="text/javascript">
    function SubmeterForm(id)
    {
        if (id=='btnOk')
            document.forms[0].submit(id);
        else
            document.forms[1].submit(id);
    }
</script>


<% Html.BeginForm("ObterNomeBotaoClicado/1", "Teste01", FormMethod.Post); %>
<input id="btnOk" type="button" value="Ok" onclick="javascript:SubmeterForm('btnOk')" />
<% Html.EndForm(); %>
<% Html.BeginForm("ObterNomeBotaoClicado/2", "Teste01", FormMethod.Post); %>
<input id="btnCancelar" type="button" value="Cancelar" onclick="javascript:SubmeterForm('btnCancelar')" />
<% Html.EndForm(); %>

在Controller中,代码是:

public ActionResult ObterNomeBotaoClicado(string id)
{
    if (id=="1")
        btnOkFunction(...);
    else
        btnCancelarFunction(...);
    return View();
}

我不喜欢ActionSelectName的地方是IsValidName被控制器中的每个动作方法调用;我不知道为什么会这样。我喜欢一种解决方案,每个按钮都有一个不同的名称,基于它的功能,但我不喜欢这样的事实,你必须有许多参数在动作方法中的按钮在表单。我已经为所有按钮类型创建了一个枚举:

public enum ButtonType
{
    Submit,
    Cancel,
    Delete
}

而不是ActionSelectName,我使用ActionFilter:

public class MultipleButtonsEnumAttribute : ActionFilterAttribute
{
    public Type EnumType { get; set; }

    public MultipleButtonsEnumAttribute(Type enumType)
    {
        EnumType = enumType;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        foreach (var key in filterContext.HttpContext.Request.Form.AllKeys)
        {
            if (Enum.IsDefined(EnumType, key))
            {
                var pDesc = filterContext.ActionDescriptor.GetParameters()
                    .FirstOrDefault(x => x.ParameterType == EnumType);
                filterContext.ActionParameters[pDesc.ParameterName] = Enum.Parse(EnumType, key);
                break;
            }
        }
    }
}

过滤器将在表单数据中找到按钮名称,如果按钮名称与枚举中定义的任何按钮类型匹配,它将在动作参数中找到ButtonType参数:

[MultipleButtonsEnumAttribute(typeof(ButtonType))]
public ActionResult Manage(ButtonType buttonPressed, ManageViewModel model)
{
    if (button == ButtonType.Cancel)
    {
        return RedirectToAction("Index", "Home");
    }
    //and so on
    return View(model)
}

然后在视图中,我可以使用:

<input type="submit" value="Button Cancel" name="@ButtonType.Cancel" />
<input type="submit" value="Button Submit" name="@ButtonType.Submit" />

David Findley在他的ASP上写了3种不同的选择。网络博客。

阅读文章的多个按钮以相同的形式查看他的解决方案,以及每个方案的优缺点。恕我直言,他提供了一个非常优雅的解决方案,利用属性,你装饰你的行动。

我已经为HtmlHelper创建了一个ActionButton方法。它将在OnClick事件中生成带有javascript的普通输入按钮,将表单提交给指定的控制器/动作。

像这样使用辅助器

@Html.ActionButton("MyControllerName", "MyActionName", "button text")

这将生成以下HTML

<input type="button" value="button text" onclick="this.form.action = '/MyWebsiteFolder/MyControllerName/MyActionName'; this.form.submit();">

下面是扩展方法代码:

VB。网

<System.Runtime.CompilerServices.Extension()>
Function ActionButton(pHtml As HtmlHelper, pAction As String, pController As String, pRouteValues As Object, pBtnValue As String, pBtnName As String, pBtnID As String) As MvcHtmlString
    Dim urlHelperForActionLink As UrlHelper
    Dim btnTagBuilder As TagBuilder

    Dim actionLink As String
    Dim onClickEventJavascript As String

    urlHelperForActionLink = New UrlHelper(pHtml.ViewContext.RequestContext)
    If pController <> "" Then
        actionLink = urlHelperForActionLink.Action(pAction, pController, pRouteValues)
    Else
        actionLink = urlHelperForActionLink.Action(pAction, pRouteValues)
    End If
    onClickEventJavascript = "this.form.action = '" & actionLink & "'; this.form.submit();"

    btnTagBuilder = New TagBuilder("input")
    btnTagBuilder.MergeAttribute("type", "button")

    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript)

    If pBtnValue <> "" Then btnTagBuilder.MergeAttribute("value", pBtnValue)
    If pBtnName <> "" Then btnTagBuilder.MergeAttribute("name", pBtnName)
    If pBtnID <> "" Then btnTagBuilder.MergeAttribute("id", pBtnID)

    Return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal))
End Function

c# (c#代码只是从VB DLL中反编译的,所以它可以得到一些美化…但是时间太短了:-)

public static MvcHtmlString ActionButton(this HtmlHelper pHtml, string pAction, string pController, object pRouteValues, string pBtnValue, string pBtnName, string pBtnID)
{
    UrlHelper urlHelperForActionLink = new UrlHelper(pHtml.ViewContext.RequestContext);
    bool flag = Operators.CompareString(pController, "", true) != 0;
    string actionLink;
    if (flag)
    {
        actionLink = urlHelperForActionLink.Action(pAction, pController, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    else
    {
        actionLink = urlHelperForActionLink.Action(pAction, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    string onClickEventJavascript = "this.form.action = '" + actionLink + "'; this.form.submit();";
    TagBuilder btnTagBuilder = new TagBuilder("input");
    btnTagBuilder.MergeAttribute("type", "button");
    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript);
    flag = (Operators.CompareString(pBtnValue, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("value", pBtnValue);
    }
    flag = (Operators.CompareString(pBtnName, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("name", pBtnName);
    }
    flag = (Operators.CompareString(pBtnID, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("id", pBtnID);
    }
    return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal));
}

这些方法具有各种参数,但是为了便于使用,您可以创建一些重载,只使用所需的参数。