views:

668

answers:

4

I have a feeling I'm being too "webforms" with this, but I'll ask anyway. I have a form in an ASP.NET MVC project that has some input fields and two buttons on it. One button is used to 'filter' one of the list boxes. The other is used to submit the form. My view looks something like this:

<%using (Html.BeginForm())
  {%>
   <%=Html.TextBox("SearchItems") %>
   <input type="submit" name="Command" value="Find" />
   <%=Html.ListBox("SelectedItems", new MultiSelectList(model.AvailableItems,"Id", "Name", model.SelectedItems))%>
   //Some other form fields.
   <input type="submit" name="Command" value="Send" />
    <%} %>

My action looks something like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index([Bind(Prefix = "")]SendMessageRequest model)
    {
        if (model.Command == "Find")
            return SearchItems(model);
        if (model.Command == "Send")
            return Send(model);
        throw new Exception("Invalid command.");
    }

This works- the controller chooses the correct action based on the button that was clicked. However, it is not ideal, because the input button's value is also the displayed text. If I wanted to translate this app, then the action would break. To get around this, I can use a <button> element, which allows the text and value to be different. However, this app is for Pocket IE, and apparently Pocket IE handles these differently - it submits both values for Command, which breaks the action.

Since this is for Pocket IE, I'm also pretty limited in terms of what I can do with JavaScript. Ajax is out, but I could possibly set a hidden field from the buttons' onClick.

So, my question is what's the best way to allow for a single form with multiple buttons on an MVC view? Alternatively, should I be breaking up my view into multiple forms somehow?

+1  A: 

No need for a hidden field, you can set the form's action on the button's click event.

The javascript (in jQuery) is something like:

$("#myForm").attr("action", "mvcaction");
$("#myForm").submit();

You can wrap that up in a standard function that takes a parameter which is the action for example. We're using this for standard menu items in a menu form object, it works quite well.

EDIT: Not sure if Pocket PC handles JQuery at all, though if it doesn't it should be possible to do the above in regular javascript.

Odd
+5  A: 

I would suggest multiple forms with 2 different actions. This I think is also more testable:

<% Html.BeginForm(c => c.Search(), FormMethod.Get); { %> Find

<% } %>

<% Html.BeginForm(c => c.Send(), FormMethod.Post); { %> Send

<% } %>

or something like that. Then in the controller you have 2 corresponding actions. This means the responsibility is broken out. With MVC you can have multiple forms, unlike in Webforms. So you can break free!

Trevor de Koekkoek
this should also remove the problem of supporting javascript
Trevor de Koekkoek
The issue with that approach is that in this case, the "Search" form must be _inside_ the "Send" form, and all values on the page must persist. In this solution, if the user enters something in the Send form, then Searches, the Send form will lose it's state (except in FireFox).
Daniel
+1  A: 

Here's a very good article describing all the alternatives for multiple buttons forms: http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx

Personally I agree with Odd, the jQuery onclick actions seems the best option.

Igor Brejc
But then you rely on JavaScript to control page behaviour. Pages should work fine with JavaScript disabled, so it wouldn't be ideal.
Kezzer
A: 

The app I am creating needs to be massively ajax'd up, however the multiple forms problem hit as well.

We got round it using the $.post() method from the jQuery library.

$("#update").click(function() {
                $.post("/Register", { name: $("#firstName").val(),
                    surname: $("#surname").val(),
                    username: $("#email").val(),
                    accountName: $("#accountName").val(),
                    password: $("#password").val()
                },
                  function(data) {
                      alert(data);
                  });
            });

And the cancel button sent fewer values back.

$("#cancel").click(function() {
                $.post("/Cancel", { username: $("#email").val(),
                    password: $("#password").val()
                },
                  function(data) {
                      alert(data);
                  });
            });

Ok again its reliant on javascript being enabled, but if you are going to disable javascript you best not use the internet (and my app 'cause it will be heavy on the js).