With any web page, you need to execute code on the server in response to user actions. With traditional web forms, this was accomplished with event handlers generally tied to buttons, and links. With MVC, we have this concept of an "action method". So, the question becomes, how do we kick off action methods? There are 3 big ways to do this:
- The user enters a url and the routing system kicks off the action method associated with the route. The parameters of the action method are in the route itself, or exist as query parameters. Technically this is a GET request.
- The user clicks a link defined by the Html.ActionLink method. ActionLink will generate a url that contains the route necessary to execute the specified action method on the specified controller with the provided parameters. Technically this is a GET request.
- Within a form element, the user clicks on a button with the "type" attribute set to "submit". The action method associated with the form is executed. Parameters are provided through model binding. Technically this is a POST request.
One and Two are really doing the same thing. So, we are either doing a GET with a link, or a POST with a button. When do we use a GET link, and when do we use a POST button?
Standard practice is to use a GET link if we are not changing anything and POST button when are changing something.
What is model binding? First of all model binding only occurs during a POST. It's not going to happen if you are kicking off an action method through a link (such as creating one with Html.ActionLink). Any parameters for the action method associated with the form will be automatically provided based on matching up the names of the ids on the page with the names of the parameters. So if you have a hidden field with an id of "Price", and you have a parameter of your action method named "Price", this will automatically be sent to the action method when you POST.
Some people are fond of everything being a button, even stuff that shouldn't be a POST. For example, a "Cancel" button. One option is...
Create a button and make it behave like a link. Setting the type attribute to "button" will prevent the button from doing a POST
<button id="cancelButton" type="button">Cancel</button>
Then in your jQuery file,
$("#cancelButton").click(function () {
window.location = '../ActionName/' + $("#inputParameterId").val()
});
I don't particularly care for this solution. Feels like a hack to me.
Some might want everything to be a link, even though a "Save" button should be a POST. We could...
Create a link and make it behave like a submit button.
<a id="LinkSave" href="#">Link Save</a>
Then, in your jQuery file,
$("#LinkSave").click(function () {
$("#myForm").submit();
});
AND, to get this to work, your form has to have an ID, so you have to do some extra stuff with your Html.BeginForm helper...
@Using Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, New With {.id = "myForm"})
Besides being ugly and a hack, this only works in IE. So I don't like that either.
Your best bet is to leave POSTing to buttons and GETting to links. If you apply css in a smart way, you can style them to look the same. For example:
<div class="actionButtons">
<input name="Save" type="submit" value="Save" />
@Html.ActionLink("Cancel", "ApplicationSummary", New With {.id = Model.Nutshell.ApplicationId})
</div>
The CSS looks like this:
.actionButtons A, .actionButtons INPUT {
font-size: 10pt;
color: White;
margin: .5em;
font-weight: normal;
text-decoration: none;
padding: .15em 1.5em .2em 1.5em;
background-color: #353535;
border: 1px solid black;
}
So, any anchor or input tags inside a container with the "actionButtons" class will have this style.
One final note. What if you need more than one POST button on the same page? You could put two submit buttons within the same form and differentiate between the two in the action method using something like:
If Request("Save") IsNot Nothing Then
'Save Logic Here
ElseIf Request("Verify") IsNot Nothing Then
'Verify Logic Here
End If
I don't like that because it's hackish and messy. Just put two or more forms on the page, and have each form target a different action method for each submit button.
UPDATE: OK, so having two forms isn't always practical. What if you need to submit the same data, but in two different ways depending on what button is clicked? Go ahead, and put to submit buttons on your form. Make sure the name attribute is identical. Let's name them both "TheViewButton". The value attribute will obviously be different. Your action method will look like this:
<HttpPost>
Function TheViewName(viewModel As TheViewModel, TheViewButton As String) As ActionResult
If TheViewButton = "Save" Then
'Save Logic
Else
'Other Logic
End If
End Function
I like this solution a bit better.