Multiple submit buttons with different actions and controllers but shared input name/values

EDIT: Read the bottom of my question to see what I actually did. I accepted a different answer, though because my solution requires AngularJS.


I'm using C# 4.0 and MVC 3/Razor. I'd prefer to leverage existing functionality of the framework rather than make my own helper classes. Here's what I'm doing, simplified:

Here's my model:

MyModel.cs

public class MyModel
{
    public string Name { get; set; }
    public int ID { get; set; }
}

And my view, so far:

Index.cshtml

@model IEnumerable<MyModel>

Please select a Model.

<select name="id">
    @foreach (var m in Model)
    {
        <option value="@(m.ID)">@(m.ID) - @(m.Name)</option>
    }
</select>

And my controller:

MyController.cs

public class MyController : Controller
{
    public ActionResult Index() { /* ... */ }
    public ActionResult Display(int id) { /* ... */ }
    public ActionResult Delete(int id) { /* ... */ }
    public ActionResult Edit(int id) { /* ... */ }
}

In my view, I want to have three submit buttons, each linking to a different controller/action, one for Edit, Delete and Display. However I would like the ID that the user has selected to be passed (via GET). How do I do this?

I know I could make a new controller action whose sole purpose is to determine which of the three to choose, based on the value of a submit type input element, but that approach seems ugly to me; I'd like to bypass that step. Ideally I'd want something like:

@using (Html.BeginForm("", "", FormMethod.Get))
{
    <select name="id">
        @foreach (var m in Model)
        {
            <option value="@(m.ID)">@(m.ID) - @(m.Name)</option>
        }
    </select>

    @Html.SubmitButton("Edit", "My")
    @Html.SubmitButton("Delete", "My")
    @Html.SubmitButton("Display", "My")
}

But I can't find any method signatures in Html that seem to do something like that.


EDIT:

Here's what I ended up going with. It uses a JavaScript library called AngularJS, but requires no additional JavaScript plumbing. It just works.

@model IEnumerable<MyModel>
<html>
    <head>
        <script type="text/javascript" src="../../Scripts/angular.js"></script>
    </head>
    <body ng-app>
        <select ng-model="ID">
            @foreach (var m in Model)
            {
                <option value="@(m.ID)">@(m.ID) - @(m.Name)</option>
            }
        </select>

        @{
            var forms = new[] 
            {
                new { ActionName = "Display", ControllerName = "My" },
                new { ActionName = "Edit", ControllerName = "My" },
                new { ActionName = "Delete", ControllerName = "My" }
            };

            foreach (var form in forms)
            {
                using (Html.BeginForm(form.ActionName, form.ControllerName, FormMethod.Get))
                {
                    <input type="submit" value="@(form.ActionName)" ng-disabled="ID == null"/>
                    <input type="hidden" name="id" value="{{ID}}"/>
                }
            }
        }

    </body>
</html>

You can (I have) do this using an attribute. Having tried a couple of different variations on the theme I settled with this one:

http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution/

It basically routes based on the name of your submit. For your case:

 <input type="submit" name="delete" value="Delete" />
 <input type="submit" name="Edit" value="Edit" />

and controller

public class MyController : Controller {
    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id) {
    }

    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Delete(int id) {

    }
}

the attribute

  public class HttpParamActionAttribute : ActionNameSelectorAttribute {
        public override bool IsValidName(ControllerContext controllerContext,  
                                       string actionName, MethodInfo methodInfo) 


 {

            if (actionName.Equals(methodInfo.Name,  
                                  StringComparison.InvariantCultureIgnoreCase))
                return true;

            if (!actionName.Equals("Action", 
                                   StringComparison.InvariantCultureIgnoreCase))
                return false;

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

For Edit and Display, clearly, you do not need a form submit. You can use GET for that. So Html.ActionLink helper method can be used to show a link which takes the user to approriate screens ( action methods).

To pass the Value of the selected item from the drop down in the link, you can get the selected value with java script on the click event and send that to the action method.

@Html.ActionLink("Edit","Edit","YourController",null ,new {@class="lnk"})
@Html.ActionLink("Display","Display","YourController",null ,new {@class="lnk"})
@Html.ActionLink("Delete","Delete","YourController",null ,new {@class="lnk"})

Now the javascript to capture the click event of these links

$(function(){
  $("a.lnk").click(function(e){
     e.preventDefault();
     var targetUrl=$(this).attr("href");
     var selectedVal=$("#YourDropdownID").val();
     targetUrl=targetUrl+"?id="+selectedVal;
     window.location.href=url;
  });
});

For Delete, you may show a link which takes the user to a confirmation screen and there you can have a submit button which does a HTTPPOST submit.

You can customize your CSS to make the a tag looks like a submit button

Also, Do not render the dropdown using the foreach loop in the view. There is already HTML Helper methods to do that in MVC. You should always make use of that. Here is an answer explaining how to do that.