Introduction
When I first started developing web applications with ASP.NET MVC, I struggled to learn how to create forms. Although my forms worked (thank goodness for <Ctrl-c Ctrl-v>), they were far from scalable and I wasn’t sure how they worked. The purpose of this introductory article is to help guide the beginner in creating forms. We will discuss four types of forms:
- weakly typed synchronous forms
- strongly typed synchronous forms
- strongly typed AJAX forms
- use jQuery with AJAX to post form data
To enhance your learning experience, you can fork the four form examples and experiment with them as you read along from https://github.com/NanoBreeze/CodeProject-Creating-Forms-in-ASP.NET-MVC-5.
If you already have experience creating forms, you can check out the Further Reading section for more comprehensive details on forms.
Background
Each form contains three basic elements: a <form>
element, <input>
elements (which the user can type to), and some type of a submit button.
In our example, each of our forms contains a checkbox
, a textbox
for string
s, and a textbox
for numbers because these are some of the most frequently used <input>
s.
Setup
We create a new controller, view, and model (which is really a class that contains auto-implemented properties. The model will be used by the strongly-typed form examples). Let’s name the controller “Form
” (this will create a new file called “FormController.cs” in the Controllers folder) and add a view for its Index
action method.
Next, let’s make a class “FormData.cs” in the Model folder (you can actually place the class anywhere but by convention, we place it in the Model folder) whose properties would store the user's inputs:
namespace LearningForms.Models
{
public class FormData
{
public string TextBoxStringData { get; set; }
public int TextBoxIntData { get; set; }
public bool CheckboxData { get; set; }
}
}
Weakly Typed Synchronous Forms
This is the quickest way to post a form. Each <input>
's name must match one parameter’s name in the method the form is posted to. The characters or digits that users type into <input>
elements become part of the <input>
’s value attribute and since <input>
values are passed from client to server by matching names, make sure there are no typos.
Client (Index.cshtml under ~/Views/Forms)
<form action="/Form/FormOne" method="post">
<input type="text" name="textBoxStringData" />
<input type="checkbox" name="checkboxData" />
<input type="number" name="textBoxIntData" />
<input type="submit" value="Submit weakly typed form" />
</form>
Notes
- The
<form>
element. This is the parent element for all form-related elements, including <input>
s.
action
indicates the method the form is posted to (aka, the method that will receive the value of the <input>
element, which the user has typed in before submitting the form).
method
specifies the HTTP verb we’re using. Setting method="post"
ensures that the information in this form can only be sent to the server from a form or from JavaScript and not from the URL. You can learn more about HTTP verbs here.
- The
<input>
elements. Users type data into the input elements.
type
indicates the type of data the input accepts. E.g., textbox
, checkbox
, radio button, submit button
name
is very important and it must match the parameter names of the method the form is posted to
Server
Make a new method in FormController.cs called FormOne
that accepts parameters whose names are identical to the names of the <input>
elements. Let’s also provide the method a [HttpPost]
attribute:
[HttpPost]
public void FormOne(string textBoxStringData, int textBoxIntData, string checkboxData)
{
}
Notes
- Parameter names. These must be identical to
<input>
names. If they are different, <input>
values will not pass to FormOne
.
[HttpPost]
attribute. Ensures that the information in this form can only be sent to the server from a <form>
or from JavaScript and not from the URL. This is why we had set method=”post”
in the <form>
element
Checkbox
. If the checkbox
were checked, checkboxData
’s value would be "on"
. If it were unchecked, its value would be null
. You might have been surprised to see we set checkboxData
‘s data type to be a string
instead of a bool
. This is because if checkboxData
were bool
type, the system would throw an exception and if checkboxData
were a bool?
type, its value would always be null
independent of whether it were checked or unchecked.
Next Steps
After the user submits a form, the page usually redirects to another page. We can change the return type of FormOne
to ActionResult
and return a RedirectToAction(“ActionName”);
to redirect the user to another page. You can check this article’s source code for an example.
Strongly Typed Synchronous Forms
In a strongly typed form, we pass from the client to the server an object (the model) whose properties contain the <input>
values instead of passing many primitives. An advantage of using strongly typed forms is easier maintainability. Unlike weakly typed forms, typos are unlikely to happen. Also, the method the form is posted to has fewer parameters.
Client
The client uses HTML Helpers to represent the <form>
and <input>
elements. We also include our model object at the top of the file:
@using (Html.BeginForm("FormTwo", "Form", FormMethod.Post))
{
@Html.TextBoxFor(m => m.TextBoxStringData)
@Html.CheckBoxFor(model => model.CheckboxData)
@Html.TextBoxFor(model => model.TextBoxIntData)
<input type="submit" value="Submit strongly type synchronous form" />
}
Notes
@model.
The general syntax is @model namespace.className
. Here, FormData
is the object that is passed from the client to server. To assign <input>
values to FormData
properties, we use…
- Html helpers (e.g.,
Html.BeginForm
and @Html.TextBoxFor( m=> m.TextBoxStringData)
Html.BeginForm(...)
. When rendered on a webpage, this actually displays as a <form>
element. The first two arguments in BeginForm
are the names of the method and
@Html.TextBoxFor(m => m.TextBoxStringData)
. I know what you’re thinking: what’s up with the argument? Yepp, those were my thoughts as well. The argument is a lambda expression and it basically means that m
is the instance of our model object (Forms.Models.FormData
) and the <input>
’s value is stored in Forms.Models.FormData.TextBoxStringData
Server
Make a new method in FormController.cs called FormTwo
:
[HttpPost]
public void FormTwo(Models.FormData formData)
{
}
Notes
FormTwo
has a single parameter whose type is our model object! This can be more convenient than using weakly typed forms because if we later decide to add another <input>
to our <form>
, we simply add another property to FormData
and an Html helper to Html.BeginForm
, without changing the parameters in FormTwo
.
Strongly Typed Asynchronous Forms
We combine the advantages of strongly typed form with AJAX. This is similar to a strongly typed synchronous form
Client
@using (Ajax.BeginForm("FormThree", "Form",
new AjaxOptions { LoadingElementId = "loader", OnSuccess = "onSuccess" }))
{
@Html.TextBoxFor(m => m.TextBoxStringData)
@Html.CheckBoxFor(m => m.CheckboxData)
@Html.TextBoxFor(m => m.TextBoxIntData)
<input type="submit" value="Submit strongly typed asynchronous form" />
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
Notes
Ajax.BeginForm(…)
. the first two arguments are the same as in Html.BeginForm
. The third argument includes information about our AJAX request, such as which JavaScript function to call after the successful completion of an AJAX post.
- jQuery scripts. Remember to include jQuery as well as jQuery unobtrusive Ajax, which can be installed by typing in the Package Manager:
Install-Package jQuery.Ajax.Unobtrusive
Make sure that the script containing jQuery is placed above the script containing jQuery unobtrusive ajax.
Server
Same as for strongly typed synchronous forms:
[HttpPost]
public void FormThree(Models.FormData formData)
{
}
Next Steps
We can make a dialog appear while the server is processing the AJAX post.
Add LoadingElementId = "loader"
as a property to AjaxOptions.
Then, place somewhere on the same file:
<div id="loader" style="display:none">
Loading...
</div>
When the form is submitted and being processed by the server, ‘Loading...” will appear on the screen.
Using jQuery with AJAX to Post Data
We will be using a bit of JavaScript in this example. An advantage of using jQuery to post data is that the data is not restricted only to <input>
s. They can also be the text of <p>
s or class names of an element.
Client
<input type="text" id="text" />
<input type="checkbox" id="checkbox" />
<input type="number" id="number" />
<button onclick="submit()">Post with jQuery AJAX</button>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
//submit data with jQuery AJAX
function submit() {
var data = {
TextBoxStringData: $( TextBoxIntData: $( CheckboxData: $( };
$.post("/Form/FormFour", { formData: data },
function () { alert( }
Notes
$.post(…)
. This performs an AJAX post. The first argument is the path of the method the form posts to; the second argument is the object to post (like a model); and the third is a callback function that executes if the post is successful.
- Make sure the property of the second argument in
$.post(...)
is equal to the name of the FormData
parameter in the method the form is posted to. In addition, make sure that the data’s property names are identical to FormData
’s property names.
Server
[HttpPost]
public void FormFour(Models.FormData formData)
{
}
Thanks for reading! Hopefully, this article helped you gain a greater understanding of creating forms in MVC 5.