3 Ways To Receive Data From "Postbacks" in ASP.NET MVC

August 21st, 2015

Since IsPostback is not available in ASP.NET MVC, how do you pass data back to the controller? In this post, I show you three ways for your controller to receive postback data.

Ahh...postbacks.

How many people miss the WebForms IsPostback?

Hands? Anyone? Anyone?

Yeah, I thought so.

With ASP.NET MVC, we have a new way to post data back to the server. When users post data from a View, there are a number of ways that the controller can receive that data.

Today, I'll go over three ways to post data back to the server and give my preferred way of posting data.

As you move through these methods, keep in mind that these demos do not include any kind of sanitizing of data. ALWAYS assume that users are posting back malicious data.

Let's set up our basics for our View.

@using (Html.BeginForm("Index", "Login", FormMethod.Post, new { @area = "Admin", @role = "form" }))
{
    @Html.AntiForgeryToken()
    <div class="body bg-gray">
        <div class="form-group">
            @Html.TextBoxFor(e => e.UserName, new { maxlength = 15, @class = "form-control focus", @placeholder = "User ID" })
        </div>
 
        <div class="form-group">
            @Html.PasswordFor(e => e.Password, new { @class = "form-control", @placeholder = "Password" })
        </div>
 
    </div>
 
    <div class="footer">
        <button type="submit" class="btn bg-olive btn-block">Sign me in</button>
    </div>
}

Our model is a Login object with a UserName and Password property.

Method 1 - Passing variables

When you have an object as your model, all form elements are available in your method signature on postback.

[HttpPost, ValidateAntiForgeryToken]
public ActionResult Index(string UserName, string Password)
{
    // Do what you will with Username & Password
}

The parameters must match the form variables exactly. It's case-sensitive.

However, while this is an easy method for one or two variables passed back from your view, it's hardly a perfect solution.

If you had a large ViewModel, can you imagine a long list of variables passed back through the method signature? Ughh.

Let's look at a better way to receive the form variables.

Method 2 - FormCollection

The developers of MVC thought the amount of parameters passed into a method would be an issue, so they took the postback data and placed all of the name/value pairs into a class called a FormCollection to the controller.

This is definitely better than the previous method of passing each parameter back to the controller.

[HttpPost, ValidateAntiForgeryToken]
public ActionResult Index(FormCollection forms)
{
    var username = forms["UserName"];
    var password = forms["Password"];
 
    // Do what you will with Username & Password
}

Ok, that's a little better, but again, if we have a large ViewModel, all we did was transfer our congestion of variables from the method signature to the code. Now we have to do the "left = right" assignment of variables in our method.

Kind of time consuming and a waste of effort.

Method 3 - ViewModel

The better way to handle the hydration of objects is to use the DefaultModelBinder.

For the default model binder to work properly, you must pass the same object (or descendant class) used in your View to your POST method.

That way, the default model binder sees what ViewModel is used in your View and uses reflection to populate that ViewModel. Then, it passes it onto the controller.

[HttpPost, ValidateAntiForgeryToken]
public ActionResult Index(Login login)
{
    // Do what you will with the login model
}

At this point, the controller can update another object using the TryUpdateModel or UpdateModel and then save the object to the database.

This is my preferred way of passing back data from a View because it's a cleaner way of controlling and manipulating the data. This even works with complex objects.

If you are using large ViewModels, try to use shallow objects (one-level access). Try to use a maximum of "two-dot" levels (i.e. Model.User.Username).

NOTE: If a ViewModel gets too complicated, you may need to use a custom ModelBinder. I talk about custom model binders here and show how to unit test model binders here.

Conclusion

In this post, we discussed the various ways of posting data back from a View to the controller for saving or loading our data.

In my opinion, method 3 is the most versatile and flexible way of posting data back. It's delivered to the controller in a nice little package for us to use as we see fit.

For those new to ASP.NET MVC, this is a new concept of thinking when performing postbacks, but it's the way other languages (PHP, Java, etc.) perform postbacks.

It's called the Web.

NOTE: If you want to look at the reverse process of passing data from the controller to the View, check out the complimentary post called ASP.NET MVC Views: Passing Data To Views.

Did I miss a method? Post your comments below.