5

Is it possible to have two inputs, or button controls, trigger two different actions within the same controller bound to Html.BeginForm?

In the following example, I want the Subscribe input to call Subscribe action on the controller. This works well. I want the Unsubscribe input to call my Unsubscribe action. How do I make this happen? TIA.

<% using (Html.BeginForm("Subscribe", "NewsLetter"))
    {%>    
        <div class="editor-field">
            <%= Html.TextBoxFor(model => model.EmailAdress) %>
            <%= Html.ValidationMessageFor(
                model => model.EmailAdress) %>                                
        </div>                        
        <div >
            <input type="submit" class="submit" value="Subscribe" />
            <input type="submit" class="submit" value="Unsubscribe" />
        </div>         
<% } %>

Update:

Just more context to this question:

My NewsLetterController has two actions Subscribe and Unsubscribe as posted below:

public class NewsLetterController : Controller
    {      
        [HttpPost]
        public ActionResult Subscribe(NewsletterSubscriber subscriber)
        {
           // do something

        }

        [HttpPost]
        public ActionResult Unsubscribe(NewsletterSubscriber subscriber)
        {
            // do something
        }

I was hoping that I can invoke each action from the same Form element, but this apparently is false. How do I still maintain the MVC pattern but avoid scripting if possible? The posted HTML is part of a partial view rendered on the main page.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl
                                   <AkwiMemorial.Models.NewsletterSubscriber>" %>

   <h2><strong>Newsletter</strong></h2>
    <legend>Enter your email</legend>

    <% using (Html.BeginForm("Subscribe", "NewsLetter"))
       {%>    
            <div class="editor-field">
                <%= Html.TextBoxFor(model => model.EmailAdress) %>
                <%= Html.ValidationMessageFor(model => model.EmailAdress) %>
            </div>                        
           <div >
             <input type="submit" class="submit" name="sub" 
                    value="Subscribe" />
              <input type="submit" class="submit" name="unsub" 
                     value="Unsubscribe" />
            </div>         
    <% } %>
1
  • Please just edit your question if you need to add additional information. Commented Feb 10, 2011 at 16:26

3 Answers 3

8

An HTML form element has only one action. So unless your buttons change that with JavaScript, each form gets only one URI. Do you want your site to work with JavaScript enabled only?

Another option is to give the buttons a name, in which case you'll get the value as part of the posted form, e.g.:

<input type="submit" class="submit" name="newsletter" value="Subscribe" />
<input type="submit" class="submit" name="newsletter" value="Unsubscribe />

Then you can have a single action which checks the value, e.g.:

public ActionResult Subscribe(string newsletter)
{
    if ("subscribe".Equals(newsletter, StringComparison.OrdinalIgnoreCase))
    {
        //...

Because newsletter is a key in the posted form, MVC will bind its value to the action's argument.

Sign up to request clarification or add additional context in comments.

2 Comments

The "Subscribe" method in NewsLetterController looks like this: public ActionResult Subscribe(NewsletterSubscriber subscriber). Based on your recommendation, how can I get the button name passed into this method with the NewsletterSubscriber instance?
The NewsletterSubscriber type would need to have a property with the same name as the name attribute of the submit input.
1

Or using the RedirectToAction

   <%using(Html.BeginForm("RedirectingAction", "NewsLetter")){ %>

   <input type="submit" class="submit" name="newsletter" value="Subscribe" />
    <input type="submit" class="submit" name="newsletter" value="Unsubscribe" /> 
    <%} %>

and in the controller:

    public ActionResult RedirectingAction()
    {
        TempData["Form"] = Request.Form;
        return RedirectToAction(Request.Form["newsletter"].ToString());
    }
    public ActionResult Subscribe()
    {
        // Do stuff
        return View();
    }
    public ActionResult Unsubscribe()
    {
        //Do something else
        return View();
    }

4 Comments

Don't do that. You've just made public actions which mutate server state on a HTTP GET. And they break if your Session happens to expire during the redirect. Whichever solution he picks, he should stick to a POST and a single request, like the code in his question.
agreed. Now the question was mentionning an existing Unsubscribe Action from my understanding, hence the RedirectToAction. Your binding and everything can still happen on the RedirectingAction.
Thanks for this answer but Craig says I should be cautions with this approach. Will see what others have to say as I have not yet received a working solution that avoid javascripting.
Redirecting is the wrong thing to do here. Actually, any GET is wrong for this, but doing it on a redirect is even worse.
0

You can accomplish this using jquery:

function Subscribe()
{
  $.post(urlToSubscribeAction, $('#formId').serialize(), function () {// Do something after post});
  return false;
}

function UnSubscribe()
{
   $.post(urlToUnsubscribe, $('#formId').serialize(), function() { // Do something after post});
   return false;
}

Add an onclick handler to the submit buttons that will call your javascript functions and then do a post of the form to the correct url. Make sure to replace formId with the corect Id of your form element.

<input type="submit" class="submit" value="Subscribe" onclick="Subscribe()" />
<input type="submit" class="submit" value="Unsubscribe" onclick="Unsubscribe()" />

1 Comment

Thanks for suggestion. I do not want to introduce jquery at this stage if I can get away with it. Also, your suggestion will require I have more code on my page, instead of the controller.,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.