Back to: ASP.NET Core Tutorials For Beginners and Professionals
Model Binding using FromForm in ASP.NET Core MVC:
In this article, I will discuss How to Use FromForm Attribute to Perform Model Binding in an ASP.NET Core MVC Application with Examples. Please read our previous article discussing the basic concepts of Model Binding in ASP.NET Core MVC. Model Binding in ASP.NET Core MVC simplifies handling HTTP requests by automatically mapping data from the request to action method parameters. The FromForm Attribute in ASP.NET Core MVC is a Model Binding Attribute.
What is FromFormAttribute in ASP.NET Core MVC?
The FromForm Attribute in ASP.NET Core MVC indicates that an action method parameter should be bound from the HTTP request’s form data (PUT or POST Requests). It tells the model binder to look for the parameter’s value in the request’s form data, which comes from an HTML form submission with the content type application/x-www-form-urlencoded or multipart/form-data. That means it binds the HTML Form Fields with action method parameters.
This is common in ASP.NET Core MVC applications, where we created HTML forms that use the POST or PUT method to submit data to the server. If you go to the definition of the FromFormAttribute class, you will see the following.
As you can see, the class has two parameters. They are as follows:
BindingSource Property of FromFormAttribute in ASP.NET Core MVC
The Binding Source of the FromFormAttribute refers to the specific location from where the data is bound in an HTTP request. In the case of FromFormAttribute, this property is set to BindingSource.Form, which tells the model binder to look for values in the form data of the request body. This form data is typically submitted via an HTML form using a POST method with a content type of either application/x-www-form-urlencoded or multipart/form-data.
Name Property of FromFormAttribute in ASP.NET Core MVC
The Name property of the FromFormAttribute is used to specify a different name for the form field when the name of the method parameter or model property does not match the name of the form field. By default, the model binder will match the parameter or property name with the form field name. However, if the form field name differs from the property or parameter name, we can use the Name property to specify the form field to bind explicitly. This is useful in scenarios where the form field names differ from your model properties or action method parameters.
Example to Understand FromForm Attribute in ASP.NET Core MVC
Let us understand how to use FromFormAttribute in ASP.NET Core MVC with examples. First, create a class that represents the form data. For example, if we have a form for user registration, we need to create a model with properties such as ID, Name, Email, Password, Mobile, etc. So, first, create a class file named User.cs within the Models folder and then copy and paste the following code.
namespace ModelBindingDemo.Models { public class User { public int? Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Password { get; set; } public string Mobile { get; set; } public string Gender { get; set; } public string Country { get; set; } public DateTime? DateOfBirth { get; set; } public List<string>? Hobbies { get; set; } } }
Using FromFormAttribute in ASP.NET Core MVC:
We can use the FromFormAttribute by decorating an action method parameter or a property in an action method with [FromForm] Attribute. This tells the ASP.NET Core Model Binder to bind the data from the form part of the request to the parameter or property. So, create a new Empty MVC controller named UsersController within the Controllers folder and copy and paste the following code. As you can see, the Post version of the Create action method parameter is decorated with the [FromForm] attribute for the User Parameter.
using Microsoft.AspNetCore.Mvc; using ModelBindingDemo.Models; namespace ModelBindingDemo.Controllers { public class UsersController : Controller { [HttpGet] public IActionResult Create() { // Initialize the User model and pass it to the view var model = new User(); ViewBag.Countries = new List<string> { "United States", "Canada", "United Kingdom", "Australia", "India" }; ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Gaming", "Cooking" }; return View(model); } [HttpPost] public IActionResult Create([FromForm] User user) { if (!ModelState.IsValid) { ViewBag.Countries = new List<string> { "United States", "Canada", "United Kingdom", "Australia", "India" }; ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Gaming", "Cooking" }; return View(user); } // Process the Model, i.e., Save user to database // Redirect to another action after successful operation return RedirectToAction("Success", user); } [HttpGet] public IActionResult Success(User user) { return View(user); } } }
In the above example, when the form is submitted, the data from the form body is automatically bound to the User object of the Create action method (Create method, which is decorated with HttpPost Attribute) using the FromForm attribute. The FromForm attribute maps the posted form data to the User object.
Create a Form in a View:
Next, we need to create a view and a form inside the view for the user to submit data. The form inputs’ name attributes must match the properties of the User model. So, create a view named Create.cshtml within the Views/Users folder and copy and paste the following code. Here, the User is the model for the following, and we are using Tag Helpers to create the view and avoid name mismatch.
@model ModelBindingDemo.Models.User @{ ViewData["Title"] = "Create"; } <div class="container mt-5"> <div class="card shadow-sm"> <div class="card-header text-center bg-primary text-white"> <h2>User Registration Form</h2> </div> <div class="card-body"> <form method="post" asp-controller="Users" asp-action="create"> <div class="mb-3 row"> <label asp-for="Name" class="col-sm-3 col-form-label">Name</label> <div class="col-sm-9"> <input asp-for="Name" type="text" class="form-control" placeholder="Enter Your Name" /> </div> </div> <div class="mb-3 row"> <label asp-for="Email" class="col-sm-3 col-form-label">Email</label> <div class="col-sm-9"> <input asp-for="Email" type="text" class="form-control" placeholder="Enter Your Email" /> </div> </div> <div class="mb-3 row"> <label asp-for="Password" class="col-sm-3 col-form-label">Password</label> <div class="col-sm-9"> <input asp-for="Password" type="password" class="form-control" placeholder="Enter Your Password" /> </div> </div> <div class="mb-3 row"> <label asp-for="Mobile" class="col-sm-3 col-form-label">Mobile</label> <div class="col-sm-9"> <input asp-for="Mobile" class="form-control" placeholder="Enter Your Mobile Number" /> </div> </div> <div class="mb-3 row"> <label asp-for="Gender" class="col-sm-3 col-form-label">Gender</label> <div class="col-sm-9"> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Male" /> <label class="form-check-label">Male</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Female" /> <label class="form-check-label">Female</label> </div> </div> </div> <div class="mb-3 row"> <label asp-for="Country" class="col-sm-3 col-form-label">Country</label> <div class="col-sm-9"> <select asp-for="Country" class="form-select"> <option value="">Select Country</option> @foreach (var country in ViewBag.Countries as List<string>) { <option value="@country">@country</option> } </select> </div> </div> <div class="mb-3 row"> <label asp-for="Hobbies" class="col-sm-3 col-form-label">Hobbies</label> <div class="col-sm-9"> @foreach (var hobby in ViewBag.Hobbies as List<string>) { <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" name="Hobbies" value="@hobby" @(Model.Hobbies != null && Model.Hobbies.Contains(hobby) ? "checked" : "") /> <label class="form-check-label">@hobby</label> </div> } </div> </div> <div class="mb-3 row"> <label asp-for="DateOfBirth" class="col-sm-3 col-form-label">Date of Birth</label> <div class="col-sm-9"> <input asp-for="DateOfBirth" type="date" class="form-control" /> </div> </div> <div class="text-center"> <button type="submit" class="btn btn-success btn-lg">Register</button> </div> </form> </div> </div> </div>
Creating the Success View:
Next, create a view named Success.cshtml within the Views/Users folder and then copy and paste the following code:
@model ModelBindingDemo.Models.User @{ ViewData["Title"] = "Registration Success"; } <div class="container mt-5"> <div class="card shadow-sm"> <div class="card-body"> <div class="alert alert-success text-center" role="alert"> <h1 class="alert-heading">🎉 Registration Successful!</h1> <p class="lead">Welcome @Model.Name!</p> <p>Your registration has been completed successfully. Below are the details you provided:</p> </div> <hr> <div class="row"> <div class="col-md-6"> <p><strong>📛 Name:</strong> @Model.Name</p> </div> <div class="col-md-6"> <p><strong>📧 Email:</strong> @Model.Email</p> </div> <div class="col-md-6"> <p><strong>📱 Mobile:</strong> @Model.Mobile</p> </div> <div class="col-md-6"> <p><strong>👤 Gender:</strong> @Model.Gender</p> </div> <div class="col-md-6"> <p><strong>🌍 Country:</strong> @Model.Country</p> </div> <div class="col-md-6"> <p><strong>🎂 Date of Birth:</strong> @Model.DateOfBirth?.ToString("d")</p> </div> <div class="col-12"> <p><strong>🎯 Hobbies:</strong> @string.Join(", ", @Model.Hobbies ?? new List<string>())</p> </div> </div> <hr> <div class="text-center"> <a asp-action="Create" asp-controller="Users" class="btn btn-primary btn-lg">Create New User</a> </div> </div> </div> </div>
Run the application and create a new user by visiting the /Users/Create URL. You will see the following page asking you to enter the user details. Provide the details on the page and click the Submit button, as shown in the image below.
Once you click on the Register button, it will create a new user and redirect you to the Sucess, where you will get the following message:
Using the Name Property of FromFormAttribute and Applying FromFrom to Primitive Types:
Instead of using the Complex type, we can also use the primitive data type along with the FromForm attribute. In the example below, I show how to use the FromForm attribute with the Primitive data type and how to use the Name Property of the FromForm attribute. Suppose we have a form field named Email but want to bind it to a parameter named UserEmail. Again, we want to map the Name form field with the UserName parameter. In this case, we can use the Name property of the FromForm Attribute to map these correctly.
Let us understand this with an example. First, modify the User model as shown below. We have changed the property Name to UserName and Email to UserEmail.
namespace ModelBindingDemo.Models { public class User { public int Id { get; set; } public string? UserName { get; set; } public string? UserEmail { get; set; } public string? Password { get; set; } public string? Mobile { get; set; } public string? Gender { get; set; } public string? Country { get; set; } public List<string>? Hobbies { get; set; } public DateTime? DateOfBirth { get; set; } public bool TermsAccepted { get; set; } } }
Modifying the UsersController:
Next, modify the UsersController as follows. Here, we are using the FromForm Attribute with Primitive parameters. Also, please note that we have used the Name property of the FromForm attribute while decorating the UserEmail and UserName parameters.
using Microsoft.AspNetCore.Mvc; using ModelBindingDemo.Models; namespace ModelBindingDemo.Controllers { public class UsersController : Controller { [HttpGet] public IActionResult Create() { User user = new User(); ViewBag.Countries = new List<string> { "United States", "Canada", "United Kingdom", "Australia", "India" }; ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Gaming", "Cooking" }; return View(user); } [HttpPost] public IActionResult Create( [FromForm(Name = "Name")] string UserName, [FromForm(Name = "Email")] string UserEmail, [FromForm] string Password, [FromForm] string Mobile, [FromForm] string Gender, [FromForm] string Country, [FromForm] List<string> Hobbies, [FromForm] DateTime? DateOfBirth, [FromForm] bool TermsAccepted) { var user = new User { UserName = UserName, UserEmail = UserEmail, Password = Password, Mobile = Mobile, Gender = Gender, Country = Country, Hobbies = Hobbies, DateOfBirth = DateOfBirth, TermsAccepted = TermsAccepted }; if (!ModelState.IsValid) { ViewBag.Countries = new List<string> { "United States", "Canada", "United Kingdom", "Australia", "India" }; ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Gaming", "Cooking" }; return View(user); } // Process the Model, i.e., Save user to database return RedirectToAction("Success", user); } [HttpGet] public IActionResult Success(User user) { return View(user); } } }
Modifying the Create View:
Next, modify the Create View as follows. Here, we use the normal HTML text boxes for the Name and Email field. Please observe the field here we are providing as Name and Email, which we want to map with the UserName and UserEmail Parameter, and to achieve this, we are using the Name property of the FromForm Attribute:
@model ModelBindingDemo.Models.User @{ ViewData["Title"] = "Create"; } <div class="container mt-5"> <div class="card shadow-sm"> <div class="card-header text-center bg-primary text-white"> <h2>User Registration Form</h2> </div> <div class="card-body"> <form method="post" asp-controller="Users" asp-action="create"> <div class="mb-3 row"> <label for="Name" class="col-sm-3 col-form-label">Name</label> <div class="col-sm-9"> <input name="Name" type="text" class="form-control" placeholder="Enter Your Name" /> </div> </div> <div class="mb-3 row"> <label for="Email" class="col-sm-3 col-form-label">Email</label> <div class="col-sm-9"> <input name="Email" type="text" class="form-control" placeholder="Enter Your Email" /> </div> </div> <div class="mb-3 row"> <label asp-for="Password" class="col-sm-3 col-form-label">Password</label> <div class="col-sm-9"> <input asp-for="Password" type="password" class="form-control" placeholder="Enter Your Password" /> </div> </div> <div class="mb-3 row"> <label asp-for="Mobile" class="col-sm-3 col-form-label">Mobile</label> <div class="col-sm-9"> <input asp-for="Mobile" class="form-control" placeholder="Enter Your Mobile Number" /> </div> </div> <div class="mb-3 row"> <label asp-for="Gender" class="col-sm-3 col-form-label">Gender</label> <div class="col-sm-9"> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Male" /> <label class="form-check-label">Male</label> </div> <div class="form-check form-check-inline"> <input asp-for="Gender" type="radio" class="form-check-input" value="Female" /> <label class="form-check-label">Female</label> </div> </div> </div> <div class="mb-3 row"> <label asp-for="Country" class="col-sm-3 col-form-label">Country</label> <div class="col-sm-9"> <select asp-for="Country" class="form-select"> <option value="">Select Country</option> @foreach (var country in ViewBag.Countries as List<string>) { <option value="@country">@country</option> } </select> </div> </div> <div class="mb-3 row"> <label asp-for="Hobbies" class="col-sm-3 col-form-label">Hobbies</label> <div class="col-sm-9"> @foreach (var hobby in ViewBag.Hobbies as List<string>) { <div class="form-check form-check-inline"> <input class="form-check-input" type="checkbox" name="Hobbies" value="@hobby" @(Model.Hobbies != null && Model.Hobbies.Contains(hobby) ? "checked" : "") /> <label class="form-check-label">@hobby</label> </div> } </div> </div> <div class="mb-3 row"> <label asp-for="DateOfBirth" class="col-sm-3 col-form-label">Date of Birth</label> <div class="col-sm-9"> <input asp-for="DateOfBirth" type="date" class="form-control" /> </div> </div> <div class="text-center"> <button type="submit" class="btn btn-success btn-lg">Register</button> </div> </form> </div> </div> </div>
Modifying the Success Page:
As we have modified the User model Name and Email property to UserName and UserEmail, we need to update these two properties within the Success view. So, please modify the Success view as follows:
@model ModelBindingDemo.Models.User @{ ViewData["Title"] = "Registration Success"; } <div class="container mt-5"> <div class="card shadow-sm"> <div class="card-body"> <div class="alert alert-success text-center" role="alert"> <h1 class="alert-heading">🎉 Registration Successful!</h1> <p class="lead">Welcome @Model.UserName!</p> <p>Your registration has been completed successfully. Below are the details you provided:</p> </div> <hr> <div class="row"> <div class="col-md-6"> <p><strong>📛 Name:</strong> @Model.UserName</p> </div> <div class="col-md-6"> <p><strong>📧 Email:</strong> @Model.UserEmail</p> </div> <div class="col-md-6"> <p><strong>📱 Mobile:</strong> @Model.Mobile</p> </div> <div class="col-md-6"> <p><strong>👤 Gender:</strong> @Model.Gender</p> </div> <div class="col-md-6"> <p><strong>🌍 Country:</strong> @Model.Country</p> </div> <div class="col-md-6"> <p><strong>🎂 Date of Birth:</strong> @Model.DateOfBirth?.ToString("d")</p> </div> <div class="col-12"> <p><strong>🎯 Hobbies:</strong> @string.Join(", ", @Model.Hobbies ?? new List<string>())</p> </div> </div> <hr> <div class="text-center"> <a asp-action="Create" asp-controller="Users" class="btn btn-primary btn-lg">Create New User</a> </div> </div> </div> </div>
With the above changes in place, run the application, and it should work as expected.
When Should We Use FromForm Attribute in ASP.NET Core MVC?
We need to use the FromFormAttribute in the following scenarios:
- Form Submissions: When you expect data to be sent from a form in a POST or PUT request, such as when a user submits a registration form or a contact form.
- Handling Files: When working with file uploads in a form, especially with a multipart/form-data content type, you can use [FromForm] to bind the form data, including the files, to your model or parameters.
- Explicit Binding: When you want to explicitly specify that the data should be bound from the form, especially when you have multiple sources of data (e.g., query string, form, route data) and want to ensure that the form data takes precedence.
In the next article, I will discuss Using FromQuery to Perform Model Binding in ASP.NET Core MVC with Examples. In this article, I explain How to use FromForm to Perform Model Binding in ASP.NET Core MVC with Examples. I hope you enjoy this FromForm in ASP.NET Core MVC article.
Is there a reason for using hobbies and countries in viewBag?