Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 Model binding in HTTP GET request?

Without customization, can I do something like this in MVC 3?

    [HttpGet]
    public ViewResult MyAction(ViewModel model)
    {
        // Do stuff
        return View("ViewName", model);
    }

The reason I am doing this is to pass data between different pages as part of a work flow. (I.e. when user fnishes what's needed in step 1, pass the form data to step 2...)

like image 572
contactmatt Avatar asked Aug 15 '12 19:08

contactmatt


2 Answers

It will work as long as you have the same parameter Name as of the Property name of your Model class

Assuming your class is like this

public class ViewModel
{
  public string Name { set;get;}
  public string Loc{ set;get;}
}

You can do a Get request like this

MyAction?Name=jon&Loc=America
like image 133
Shyju Avatar answered Sep 20 '22 09:09

Shyju


Shyju's answer only works if the members of class in the endpoint's method signature contains only scalar properties. But what if you have nested classes? Let's assume that your ViewModel class looks like this:

public class ViewModel
{
    public string Name { get; set; }
    public string Title { get; set; }
    public Address MyAddress { get; set; }
}

And the Address class looks like this:

public class Address
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
}

Now let's say the GET request was done via AJAX and you did something like this in JavaScript:

var address = {
  Line1: "123 Nowhere St.",
  Line2: "Apt. B5"
}
var getRequestData = {
  Name: "Joe",
  Title: "Manager",
  MyAddress: address
}
var uriString = $.param(getRequestData); //the parameters for the GET request
$.get("/ViewResult?" + uriString, function (data) { /*callback function*/ });

Even though the shape of your address object in JavaScript perfectly matches the C# Address class in the endpoint's method signature, the Line1 and Line2 sub-properties will NOT bind. Their values will come through as null.

There are two workarounds to this.

Workaround 1:

The first is to use dot notation when naming the parameters in the GET request instead of nested JavaScript objects. Using this method, the GET request data in AJAX would look like this:

var getRequestData = {
  Name: "Joe",
  Title: "Manager",
  MyAddress.Line1: "123 Nowhere St.",
  MyAddress.Line2: "Apt. B5"
}

MVC model binding will know how to do this, as long as all your property names all match up (they are case-sensitive, so be careful).

If you're not using AJAX, but just a plain HTML form submit, it's even easier. Just name the input elements with that same dot notation. Razor syntax makes this really easy with helper methods like TextBoxFor(), but here's an example in plain HTML:

<form method="get" action="/ViewResult">
  <input type="text" name="Name" />
  <input type="text" name="Title" />
  <input type="text" name="MyAddress.Line1" />
  <input type="text" name="MyAddress.Line2" />
  <button type="submit">Submit GET request</button>
</form>

Workaround 2:

The other way around this is to simply use a POST request instead of a GET. Beware that it's technically bad practice to perform a POST request without the intent of actually changing some data on the server side, but it is an option.

like image 36
Jacob Stamm Avatar answered Sep 20 '22 09:09

Jacob Stamm