Posting form to different MVC post action depending on the clicked submit button

asp.net Mvcasp.net Mvc-4

asp.net Mvc Problem Overview


I am using ASP.Net MVC 4. I have multiple buttons on a view.. At present I am calling the same action method; and I am distinguishing the clicked button using a name attribute.

@using (Html.BeginForm("Submit", "SearchDisplay", new { id = Model == null ? Guid.NewGuid().ToString() : Model.SavedSearch }, FormMethod.Post))
{
    <div class="leftSideDiv">
        <input type="submit" id="btnExport" class="exporttoexcelButton" 
        name="Command" value="Export to Excel" />
    </div>
    
    <div class="pageWrapperForSearchSubmit">
        <input type="submit" class="submitButton" 
         value="Submit" id="btnSubmitChange" />
    </div>
}

//ACTION

    [HttpPost]
    public ActionResult Submit(SearchCostPage searchModel, string Command)
    {
        SessionHelper.ProjectCase = searchModel.ProjectCaseNumber;

        if (string.Equals(Command, Constants.SearchPage.ExportToExcel))
        {

        }
   }

QUESTIONS

  1. Is there a way to direct to different POST action methods on different button clicks (without custom routing)?
  2. If there is no way without custom routing, how can we do it with custom routing?

References:

  1. Jimmy Bogard - Cleaning up POSTs in ASP.NET MVC

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

You can choose the url where the form must be posted (and thus, the invoked action) in different ways, depending on the browser support:

In this way you don't need to do anything special on the server side.

Of course, you can use Url extensions methods in your Razor to specify the form action.

For browsers supporting HMTL5: simply define your submit buttons like this:

<input type='submit' value='...' formaction='@Url.Action(...)' />

For older browsers I recommend using an unobtrusive script like this (include it in your "master layout"):

$(document).on('click', '[type="submit"][data-form-action]', function (event) {
  var $this = $(this);
  var formAction = $this.attr('data-form-action');
  $this.closest('form').attr('action', formAction);
});

NOTE: This script will handle the click for any element in the page that has type=submit and data-form-action attributes. When this happens, it takes the value of data-form-action attribute and set the containing form's action to the value of this attribute. As it's a delegated event, it will work even for HTML loaded using AJAX, without taking extra steps.

Then you simply have to add a data-form-action attribute with the desired action URL to your button, like this:

<input type='submit' data-form-action='@Url.Action(...)' value='...'/>

Note that clicking the button changes the form's action, and, right after that, the browser posts the form to the desired action.

As you can see, this requires no custom routing, you can use the standard Url extension methods, and you have nothing special to do in modern browsers.

Solution 2 - asp.net Mvc

BEST ANSWER 1:

ActionNameSelectorAttribute mentioned in

  1. https://stackoverflow.com/questions/442704/how-do-you-handle-multiple-submit-buttons-in-asp-net-mvc-framework

  2. https://stackoverflow.com/questions/16479946/asp-net-mvc-4-form-with-2-submit-buttons-actions

http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx

ANSWER 2

Reference: dotnet-tricks - Handling multiple submit buttons on the same form - MVC Razor

Second Approach

Adding a new Form for handling Cancel button click. Now, on Cancel button click we will post the second form and will redirect to the home page.

Third Approach: Client Script

<button name="ClientCancel" type="button" 
	onclick=" document.location.href = $('#cancelUrl').attr('href');">Cancel (Client Side)
</button>
<a id="cancelUrl" href="@Html.AttributeEncode(Url.Action("Index", "Home"))" 
style="display:none;"></a>

Solution 3 - asp.net Mvc

This sounds to me like what you have is one command with 2 outputs, I would opt for making the change in both client and server for this.

At the client, use JS to build up the URL you want to post to (use JQuery for simplicity) i.e.

<script type="text/javascript">
    $(function() {
        // this code detects a button click and sets an `option` attribute
        // in the form to be the `name` attribute of whichever button was clicked
        $('form input[type=submit]').click(function() {
            var $form = $('form');
            form.removeAttr('option');
            form.attr('option', $(this).attr('name'));
        });
        // this code updates the URL before the form is submitted
        $("form").submit(function(e) { 
            var option = $(this).attr("option");
            if (option) {
                e.preventDefault();
                var currentUrl = $(this).attr("action");
                $(this).attr('action', currentUrl + "/" + option).submit();     
            }
        });
    });
</script>
...
<input type="submit" ... />
<input type="submit" name="excel" ... />

Now at the server side we can add a new route to handle the excel request

routes.MapRoute(
    name: "ExcelExport",
    url: "SearchDisplay/Submit/excel",
    defaults: new
    {
        controller = "SearchDisplay",
        action = "SubmitExcel",
    });

You can setup 2 distinct actions

public ActionResult SubmitExcel(SearchCostPage model)
{
   ...
}

public ActionResult Submit(SearchCostPage model)
{
   ...
}

Or you can use the ActionName attribute as an alias

public ActionResult Submit(SearchCostPage model)
{
   ...
}

[ActionName("SubmitExcel")]
public ActionResult Submit(SearchCostPage model)
{
   ...
}

Solution 4 - asp.net Mvc

you can use ajax calls to call different methods without a postback

$.ajax({
    type: "POST",
     url: "@(Url.Action("Action", "Controller"))",
     data: {id: 'id', id1: 'id1' },
     contentType: "application/json; charset=utf-8",
     cache: false,
     async: true,
     success: function (result) {
        //do something
     }
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLCJView Question on Stackoverflow
Solution 1 - asp.net MvcJotaBeView Answer on Stackoverflow
Solution 2 - asp.net MvcLCJView Answer on Stackoverflow
Solution 3 - asp.net MvcJamesView Answer on Stackoverflow
Solution 4 - asp.net MvcMatt BodilyView Answer on Stackoverflow