38

I have a form in ASP.Net and razor.

I need to have two ways of submitting said form: one that goes through the Edit action, and another that goes through the Validate action.

How should I go about doing this?

I don't mind using JavaScript for this.

EDIT:

Using the custom attribute I get this error.

The current request for action 'Resultados' on controller type 'InspecoesController' is ambiguous between the following action methods: System.Web.Mvc.ActionResult Validar(System.Collections.Generic.ICollection1[Waveform.IEP.Intus.Server.Web.ViewModels.ResultadoViewModel]) on type Waveform.IEP.Intus.Server.Web.Controllers.InspecoesController System.Web.Mvc.ActionResult Resultados(System.Collections.Generic.ICollection1[Waveform.IEP.Intus.Server.Web.ViewModels.ResultadoViewModel]) on type Waveform.IEP.Intus.Server.Web.Controllers.InspecoesController

jpaugh
  • 6,634
  • 4
  • 38
  • 90
Tiago Veloso
  • 8,513
  • 17
  • 64
  • 85
  • For MVC 6 see http://stackoverflow.com/questions/36555265/asp-net-mvc-core-6-multiple-submit-buttons – Softlion Dec 21 '16 at 17:29

7 Answers7

76

That's what we have in our applications:
Attribute

public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}

Actions decorated with it:


[HttpParamAction]
public ActionResult Save(MyModel model)
{
    // ...
}

[HttpParamAction]
public ActionResult Publish(MyModel model)
{
    // ...
}

HTML/Razor

@using (@Html.BeginForm())
{
    <!-- form content here -->
    <input type="submit" name="Save" value="Save" />
    <input type="submit" name="Publish" value="Publish" />
}

name attribute of submit button should match action/method name

This way you do not have to hard-code urls in javascript

Ramunas
  • 3,853
  • 1
  • 30
  • 31
  • I like your approach. However, I can't seem to get it to work. I have the `name` attribute of the button set with the name of the action in the controller. I get the exception on my question. (BTW, I did not downvote you) – Tiago Veloso May 10 '13 at 11:38
  • Can you please verify that `HttpParamActionAttribute.IsValidName()` is hit at all? If it is, what is the value of `request[methodInfo.Name]`? – Ramunas May 10 '13 at 11:45
  • `request[methodInfo.Name] "Validar" string` – Tiago Veloso May 10 '13 at 11:52
  • 2
    Do you have an `action` attribute value set for your form? `@using (Html.BeginForm())` should be enough. It's strange because at the moment of writing this comment I'm implementing exactly the same thing and it just works – Ramunas May 10 '13 at 12:02
  • I have got it to work, but now the `Validar` recieves a null parameter. – Tiago Veloso May 10 '13 at 14:31
  • Thank you! This works like magic. Creating the HttpParamAction is genius! – Termato Jan 28 '14 at 21:04
  • 3
    Good. I've renamed mine as ButtonNameActionAttribute: then the controller looks a little cleaner and a touch more obvious. – Jeremy McGee Aug 22 '14 at 14:17
  • I have problems with this. My exception: The current request for action 'Index' on controller type 'SellInstallExceptionsController' is ambiguous between the following action methods: System.Web.Mvc.ActionResult Index(Directv.UniqueAllocator.WebUI.Models.SellInstallExceptionsModels.IndexViewModel) on type Directv.UniqueAllocator.WebUI.Controllers.SellInstallExceptionsController System.Web.Mvc.ActionResult BulkDelete(Int32[]) on type Directv.UniqueAllocator.WebUI.Controllers.SellInstallExceptionsController... actionName always has the value "Index". Is this OK? – user1916015 Sep 30 '14 at 14:08
  • This approach requires specific declarations of `[HttpGet]` and `[HttpPost]`. In my case, the default route (/Index/) was receiving both GET & POST, so I was getting ambiguous route exceptions after implementing this. Once I added `[HttpGet]` to the default Action, this worked as expected. – JoeBrockhaus Oct 13 '14 at 16:09
  • 2
    this is easy in a pinch, but it causes a lot of other problems when you have other action methods in the same controller. Not to mention an implicit contract between the view and the controller (a big no-no). I've opted for a lightweight JS function that changes the form action before submitting, like @ŁukaszW.pl below – JoeBrockhaus Oct 23 '14 at 15:35
  • @Ramunas - really useful code, simple and effective, thanks very much – Nick Nov 21 '14 at 09:58
  • 1
    I like this approach. And if you would like to add HTML attributes , e.g. for Bootstrap, while keeping the default behavior of the parameterless `Html.BeginForm()` you can pass null for action and controller. Here is an example: `Html.BeginForm(null, null, FormMethod.Post, new { @class = "form-horizontal", role = "form" })` – Manfred Oct 11 '15 at 03:20
  • 1
    @Ramunas as people told you above, great solution! Not that it works, but it is also a clever approach and I like it a lot. Can't believe you received a -1, it happens to me as well every know and then - probably there are some hatters on SO. Vote up from me! :-) – Liviu Sosu May 14 '17 at 10:19
43

You can do it with jquery, just put two methods to submit for to diffrent urls, for example with this form:

<form id="myForm">
    <%-- form data inputs here ---%>
    <button id="edit">Edit</button>
    <button id="validate">Validate</button>
</form>

you can use this script (make sure it is located in the View, in order to use the Url.Action attribute):

<script type="text/javascript">
      $("#edit").click(function() {
          var form = $("form#myForm");
          form.attr("action", "@Url.Action("Edit","MyController")");
          form.submit();
      });

      $("#validate").click(function() {
          var form = $("form#myForm");
          form.attr("action", "@Url.Action("Validate","MyController")");
          form.submit();
      });
</script>
Łukasz W.
  • 9,538
  • 5
  • 38
  • 63
  • I didn't knew about `form.attr()`. This should do the trick. Thanks. – Tiago Veloso May 10 '13 at 10:19
  • With javascript/jquery you can manipulate any dom property, especially element attributes with `attr()`. If you're not sure if there is a method you need use jquery documentation (http://docs.jquery.com/) - there's a lot of knowledge.. – Łukasz W. May 10 '13 at 10:21
  • 1
    You should use the `#edit` syntax rather than `button#edit`, assuming you don't have duplicate IDs across different element types (about the only reason I could see that being used). Querying by ID is much faster. If you were using non-ID selector on the RHS, you'd be a little better off because it's paring the list down. But because the plain ID selector uses `DOM.getElementById('')` (at least, without having to first find all `button` elements), it will be faster. – JoeBrockhaus Oct 23 '14 at 15:41
  • 1
    @JoeBrockhaus - thats not related to this problem, but it's a good point so I've corrected my answer. – Łukasz W. Oct 25 '14 at 07:17
  • agreed, unrelated :) glad I could help! – JoeBrockhaus Oct 27 '14 at 17:18
  • Thx. this is the only solution that using JQuery which I can find. – Mark May 06 '16 at 03:04
8

If you are working in asp.net with razor, and you want to control multiple submit button event.then this answer will guide you. Lets for example we have two button, one button will redirect us to "PageA.cshtml" and other will redirect us to "PageB.cshtml".

@{
  if (IsPost)
    {
       if(Request["btn"].Equals("button_A"))
        {
          Response.Redirect("PageA.cshtml");
        }
      if(Request["btn"].Equals("button_B"))
        {
          Response.Redirect("PageB.cshtml");
        }
  }
}
<form method="post">
   <input type="submit" value="button_A" name="btn"/>;
   <input type="submit" value="button_B" name="btn"/>;          
</form>

Ajay2707
  • 5,690
  • 6
  • 40
  • 58
Pir Fahim Shah
  • 10,505
  • 1
  • 82
  • 81
5

Here is a good eplanation: ASP.NET MVC – Multiple buttons in the same form

In 2 words:
you may analize value of submitted button in yout action
or
make separate actions with your version of ActionMethodSelectorAttribute (which I personaly prefer and suggest).

Dima
  • 6,721
  • 4
  • 24
  • 43
  • My answer is adopted version of the article :) – Ramunas May 10 '13 at 10:38
  • Perfect! Nice quick and easy implementation to use rather than clutter code in the view with JQuery/Javascript BTW, for custom ActionMethodSelectorAttribute approach where do you put this class? Does it need to be registered to the framework some how? – eaglei22 Dec 09 '15 at 14:57
4

With HTML5 you can use button[formaction]:

<form action="Edit">
  <button type="submit">Submit</button> <!-- Will post to default action "Edit" -->
  <button type="submit" formaction="Validate">Validate</button> <!-- Will override default action and post to "Validate -->
</form>
Andreas Ågren
  • 3,879
  • 24
  • 33
3

<input type="submit" value="Create" name="button"/>
<input type="submit" value="Reset" name="button" />

write the following code in Controler.

[HttpPost]
        public ActionResult Login(string button)
        {
            switch (button)
            {
                case "Create":
                    return RedirectToAction("Deshboard", "Home");
                    break;
                case "Reset":
                    return RedirectToAction("Login", "Home");
                    break;
            }

            return View();
        }
Jeetendra Negi
  • 443
  • 3
  • 3
1

We can have this in 2 ways,

Either have 2 form submissions within the same View and having 2 Action methods at the controller but you will need to have the required fields to be submitted with the form to be placed within

ex is given here with code Multiple forms in view asp.net mvc with multiple submit buttons

Or

Have 2 or multiple submit buttons say btnSubmit1 and btnSubmit2 and check on the Action method which button was clicked using the code

if (Request.Form["btnSubmit1"] != null)
{
 //
}
if (Request.Form["btnSubmit2"] != null)
{
 //
}
Jeff D
  • 349
  • 3
  • 4