How do you handle multiple submit buttons in ASP.NET MVC Framework?

后端 未结 30 3034
一个人的身影
一个人的身影 2020-11-21 07:16

Is there some easy way to handle multiple submit buttons from the same form? For example:

<% Html.BeginForm(\"MyAction\", \"MyController\", FormMethod.Pos         


        
相关标签:
30条回答
  • 2020-11-21 07:40

    I would suggest interested parties have a look at Maarten Balliauw's solution. I think it is very elegant.

    In case the link dissapears, it's using the MultiButton attribute applied to a controller action to indicate which button click that action should relate to.

    0 讨论(0)
  • 2020-11-21 07:41

    Here is a mostly clean attribute-based solution to the multiple submit button issue based heavily on the post and comments from Maarten Balliauw.

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class MultipleButtonAttribute : ActionNameSelectorAttribute
    {
        public string Name { get; set; }
        public string Argument { get; set; }
    
        public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
        {
            var isValidName = false;
            var keyValue = string.Format("{0}:{1}", Name, Argument);
            var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
    
            if (value != null)
            {
                controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
                isValidName = true;
            }
    
            return isValidName;
        }
    }
    

    razor:

    <form action="" method="post">
     <input type="submit" value="Save" name="action:Save" />
     <input type="submit" value="Cancel" name="action:Cancel" />
    </form>
    

    and controller:

    [HttpPost]
    [MultipleButton(Name = "action", Argument = "Save")]
    public ActionResult Save(MessageModel mm) { ... }
    
    [HttpPost]
    [MultipleButton(Name = "action", Argument = "Cancel")]
    public ActionResult Cancel(MessageModel mm) { ... }
    

    Update: Razor pages looks to provide the same functionality out of the box. For new development, it may be preferable.

    0 讨论(0)
  • 2020-11-21 07:41

    David Findley writes about 3 different options you have for doing this, on his ASP.Net weblog.

    Read the article multiple buttons in the same form to see his solutions, and the advantages and disadvantages of each. IMHO he provides a very elegant solution which makes use of attributes that you decorate your action with.

    0 讨论(0)
  • 2020-11-21 07:43

    If you do not have restrictions on the use of HTML 5, you can use the <button> tag with formaction Attribute:

    <form action="demo_form.asp" method="get">
       First name: <input type="text" name="fname" /><br />
       Last name: <input type="text" name="lname" /><br />
       <button type="submit">Submit</button><br />
       <button type="submit" formaction="demo_admin.asp">Submit as admin</button>
    </form>
    

    Reference: http://www.w3schools.com/html5/att_button_formaction.asp

    0 讨论(0)
  • 2020-11-21 07:43

    I've created an ActionButton method for the HtmlHelper. It will generate normal input button with a bit of javascript in the OnClick event that will submit the form to the specified Controller/Action.

    You use the helper like that

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

    this will generate the following HTML

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

    Here is the extension method code:

    VB.Net

    <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# (the C# code is just decompiled from the VB DLL, so it can get some beautification... but time is so short :-))

    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));
    }
    

    These methods have various parameters, but for the ease of use you can create some overload that take just the parameters you need.

    0 讨论(0)
  • 2020-11-21 07:44

    Eilon suggests you can do it like this:

    If you have more than one button you can distinguish between them by giving each button a name:

    <input type="submit" name="SaveButton" value="Save data" />
    <input type="submit" name="CancelButton" value="Cancel and go back to main page" />
    

    In your controller action method you can add parameters named after the HTML input tag names:

    public ActionResult DoSomeStuff(string saveButton, string
    cancelButton, ... other parameters ...)
    { ... }
    

    If any value gets posted to one of those parameters, that means that button was the one that got clicked. The web browser will only post a value for the one button that got clicked. All other values will be null.

    if (saveButton != null) { /* do save logic */ }
    if (cancelButton != null) { /* do cancel logic */ }
    

    I like this method as it does not rely on the value property of the submit buttons which is more likely to change than the assigned names and doesn't require javascript to be enabled

    See: http://forums.asp.net/p/1369617/2865166.aspx#2865166

    0 讨论(0)
提交回复
热议问题