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

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

    Give your submit buttons a name, and then inspect the submitted value in your controller method:

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

    posting to

    public class MyController : Controller {
        public ActionResult MyAction(string submitButton) {
            switch(submitButton) {
                case "Send":
                    // delegate sending to another controller action
                    return(Send());
                case "Cancel":
                    // call another action to perform the cancellation
                    return(Cancel());
                default:
                    // If they've submitted the form without a submitButton, 
                    // just return the view again.
                    return(View());
            }
        }
    
        private ActionResult Cancel() {
            // process the cancellation request here.
            return(View("Cancelled"));
        }
    
        private ActionResult Send() {
            // perform the actual send operation here.
            return(View("SendConfirmed"));
        }
    
    }
    

    EDIT:

    To extend this approach to work with localized sites, isolate your messages somewhere else (e.g. compiling a resource file to a strongly-typed resource class)

    Then modify the code so it works like:

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

    and your controller should look like this:

    // Note that the localized resources aren't constants, so 
    // we can't use a switch statement.
    
    if (submitButton == Resources.Messages.Send) { 
        // delegate sending to another controller action
        return(Send());
    
    } else if (submitButton == Resources.Messages.Cancel) {
         // call another action to perform the cancellation
         return(Cancel());
    }
    
    0 讨论(0)
  • 2020-11-21 07:35

    My JQuery approach using an extension method:

    public static MvcHtmlString SubmitButtonFor<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string value) where TController : Controller
    {
        RouteValueDictionary routingValues = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action);
    
        var onclick = string.Format("$('form').first().attr('action', '/{0}')", string.Join("/", routingValues.Values.ToArray().Where(x => x != null).Select(x => x.ToString()).ToArray()));
        var html = "<input type=\"submit\" value=\"" + value + "\" onclick=\"" + onclick + "\" />";
    
        return MvcHtmlString.Create(html);
    }
    

    You can use it like this:

    @(Html.SubmitButtonFor<FooController>(c => c.Save(null), "Save"))
    

    And it renders like this:

    <input type="submit" value="Save" onclick="$('form').first().attr('action', '/Foo/Save')" >
    
    0 讨论(0)
  • 2020-11-21 07:36

    This is the technique I'd use and I don't see it here yet. The link (posted by Saajid Ismail ) that inspires this solution is http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx). It adapts Dylan Beattie's answer to do localization without any problems.

    In the View:

    <% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
    <button name="button" value="send"><%: Resources.Messages.Send %></button>
    <button name="button" value="cancel"><%: Resources.Messages.Cancel %></button>
    <% Html.EndForm(); %>
    

    In the Controller:

    public class MyController : Controller 
    {
        public ActionResult MyAction(string button)
        {
             switch(button)
             {
                 case "send":
                     this.DoSend();
                     break;
                 case "cancel":
                     this.DoCancel();
                     break;
             }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 07:37

    You can check the name in the action as has been mentioned, but you might consider whether or not this is good design. It is a good idea to consider the responsibility of the action and not couple this design too much to UI aspects like button names. So consider using 2 forms and 2 actions:

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

    Also, in the case of "Cancel", you are usually just not processing the form and are going to a new URL. In this case you do not need to submit the form at all and just need a link:

    <%=Html.ActionLink("Cancel", "List", "MyController") %>
    
    0 讨论(0)
  • 2020-11-21 07:38

    You should be able to name the buttons and give them a value; then map this name as an argument to the action. Alternatively, use 2 separate action-links or 2 forms.

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

    I'm pretty late to the party, but here goes... My implementation borrows from @mkozicki but requires less hardcoded strings to get wrong. Framework 4.5+ required. Essentially, the controller method name should be the key to the routing.

    Markup. The button name must be keyed with "action:[controllerMethodName]"

    (notice the use of the C#6 nameof API, providing type-specific reference to the name of the controller method you wish to invoke.

    <form>
        ... form fields ....
        <button name="action:@nameof(MyApp.Controllers.MyController.FundDeathStar)" type="submit" formmethod="post">Fund Death Star</button>
        <button name="action:@nameof(MyApp.Controllers.MyController.HireBoba)" type="submit" formmethod="post">Hire Boba Fett</button>
    </form>
    

    Controller:

    namespace MyApp.Controllers
    {
        class MyController
        {    
            [SubmitActionToThisMethod]
            public async Task<ActionResult> FundDeathStar(ImperialModel model)
            {
                await TrainStormTroopers();
                return View();
            }
    
            [SubmitActionToThisMethod]
            public async Task<ActionResult> HireBoba(ImperialModel model)
            {
                await RepairSlave1();
                return View();
            }
        }
    }
    

    Attribute Magic. Notice the use of CallerMemberName goodness.

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class SubmitActionToThisMethodAttribute : ActionNameSelectorAttribute
    {        
        public SubmitActionToThisMethodAttribute([CallerMemberName]string ControllerMethodName = "")
        {
            controllerMethod = ControllerMethodName;
            actionFormat = string.Concat(actionConstant, ":", controllerMethod);
        }
        const string actionConstant = "action";
        readonly string actionFormat;
        readonly string controllerMethod;
    
        public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
        {
            var isValidName = false;
            var value = controllerContext.Controller.ValueProvider.GetValue(actionFormat);
    
            if (value != null)
            {
                controllerContext.Controller.ControllerContext.RouteData.Values[actionConstant] = controllerMethod;
                isValidName = true;
            }
            return isValidName;
        }
    }
    
    0 讨论(0)
提交回复
热议问题