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

后端 未结 30 2985
一个人的身影
一个人的身影 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:47

    If your browser supports the attribute formaction for input buttons (IE 10+, not sure about other browsers) then the following should work:

    @using (Html.BeginForm()){
        //put form inputs here
    
    <input id="sendBtn" value="Send" type="submit" formaction="@Url.Action("Name Of Send Action")" />
    
    <input id="cancelBtn" value="Cancel" type="submit" formaction="@Url.Action("Name of Cancel Action") />
    
    }
    
    0 讨论(0)
  • 2020-11-21 07:50

    Here's an extension method I wrote to handle multiple image and/or text buttons.

    Here's the HTML for an image button:

    <input id="btnJoin" name="Join" src="/content/images/buttons/btnJoin.png" 
           type="image">
    

    or for a text submit button :

    <input type="submit" class="ui-button green" name="Submit_Join" value="Add to cart"  />
    <input type="submit" class="ui-button red" name="Submit_Skip" value="Not today"  />
    

    Here is the extension method you call from the controller with form.GetSubmitButtonName(). For image buttons it looks for a form parameter with .x (which indicates an image button was clicked) and extracts the name. For regular input buttons it looks for a name beginning with Submit_ and extracts the command from afterwards. Because I'm abstracting away the logic of determining the 'command' you can switch between image + text buttons on the client without changing the server side code.

    public static class FormCollectionExtensions
    {
        public static string GetSubmitButtonName(this FormCollection formCollection)
        {
            return GetSubmitButtonName(formCollection, true);
        }
    
        public static string GetSubmitButtonName(this FormCollection formCollection, bool throwOnError)
        {
            var imageButton = formCollection.Keys.OfType<string>().Where(x => x.EndsWith(".x")).SingleOrDefault();
            var textButton = formCollection.Keys.OfType<string>().Where(x => x.StartsWith("Submit_")).SingleOrDefault();
    
            if (textButton != null)
            {
                return textButton.Substring("Submit_".Length);
            }
    
            // we got something like AddToCart.x
            if (imageButton != null)
            {
                return imageButton.Substring(0, imageButton.Length - 2);
            }
    
            if (throwOnError)
            {
                throw new ApplicationException("No button found");
            }
            else
            {
                return null;
            }
        }
    }
    

    Note: For text buttons you have to prefix the name with Submit_. I prefer this way becuase it means you can change the text (display) value without having to change the code. Unlike SELECT elements, an INPUT button has only a 'value' and no separate 'text' attribute. My buttons say different things under different contexts - but map to the same 'command'. I much prefer extracting the name this way than having to code for == "Add to cart".

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

    You could write:

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

    And then in the page check if the name == "Send" or name == "Cancel"...

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

    Based on mkozicki answer I come up with a bit different solution. I still use ActionNameSelectorAttribute But I needed to handle two buttons 'Save' and 'Sync'. They do almost the same so I didn't want to have two actions.

    attribute:

    public class MultipleButtonActionAttribute : ActionNameSelectorAttribute
    {        
        private readonly List<string> AcceptedButtonNames;
    
        public MultipleButtonActionAttribute(params string[] acceptedButtonNames)
        {
            AcceptedButtonNames = acceptedButtonNames.ToList();
        }
    
        public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
        {            
            foreach (var acceptedButtonName in AcceptedButtonNames)
            {
                var button = controllerContext.Controller.ValueProvider.GetValue(acceptedButtonName);
                if (button == null)
                {
                    continue;
                }                
                controllerContext.Controller.ControllerContext.RouteData.Values.Add("ButtonName", acceptedButtonName);
                return true;
            }
            return false;
        }
    }
    

    view

    <input type="submit" value="Save" name="Save" />
    <input type="submit" value="Save and Sync" name="Sync" />
    

    controller

     [MultipleButtonAction("Save", "Sync")]
     public ActionResult Sync(OrgSynchronizationEditModel model)
     {
         var btn = this.RouteData.Values["ButtonName"];
    

    I also want to point out that if actions do different things I would probably follow mkozicki post.

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

    Here is what works best for me:

    <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();
    }
    
    0 讨论(0)
  • 2020-11-21 07:54

    For each submit button just add:

    $('#btnSelector').click(function () {
    
        $('form').attr('action', "/Your/Action/);
        $('form').submit();
    
    });
    
    0 讨论(0)
提交回复
热议问题