I would like to better understand how a controler method knows when a parameter it recives should be retrived from the post data or the url.
Take the following example:
URL: /ModelController/Method/itemID
// Where itemID is the id (int) of the item in the database
POST: objectOrArray: {JSON Object/Array}
The controller would look something like this:
[HttpPost]
public ActionResult InputResources(int? id, Object objectOrArray)
Now, somehow the method is smart enough to look for the first parameter, the id
, in the site URL and the Object
in the HTTPPost
.
Whilst this works, I don't know why, and as a result I sometimes run into unpredictable and erratic behaviour. For example, I seem to have found (although I am not 100% sure) that removing the ?
from int? id
makes the controller method inmediately assume it should look for the id in the HTTPPost
and not the URL.
So I would like to clarify the following points:
What exactly is it that tells the method where to look for the data? (The [HttpPost]
attribute preciding the method?)
Do naming conventions come into play? (for example removint the ?
or not using id
as the variable name?)
Does the order in which the variables are placed have an inpact? (ie placing the Object
before the id
)
I know I can more or less figure out some of this stuff by trial and error, but I would like a qualified explanation rather than to continiue to work of assumption based on observation.
Thank you
Chopo
Take a look at the default route from Global.asax
:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The first thing that MVC will try to do is map your method parameters to values in the POST. If it doesn't find a match, it will cascade through other possibilities, including the route values.
Here's the order the model binder uses:
- Previously bound action parameters, when the action is a child action
- Form fields (Request.Form)
- The property values in the JSON Request body (Request.InputStream), but only when the request is an AJAX request
- Route data (RouteData.Values)
- Querystring parameters (Request.QueryString)
- Posted files (Request.Files)
The reason you're seeing the behaviour you describe is because POST data comes before route values. It seems that MVC can't bind a nullable int to a POST value, so it skips over it and keeps going until it reaches the RouteData
mapping, at which point, it finds a match and gets the value from the route. When you make the parameter non-nullable, it is suddenly able to bind it to the POST value, which has higher precedence than RouteData
, so it does.
Source: http://msdn.microsoft.com/en-us/magazine/hh781022.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With