I just ran into a situation which could lead to very annoying latent bugs in your web application. Observe the following code.
The view:
<form method="post" action="Photo/Save">
<input type="text" name="Photo" />
<input type="text" name="Title" />
</form>
The Controller action:
public ActionResult Save(PhotoDTO photo)
{
// do something with the object
return RedirectToAction("Index");
}
The class:
public class PhotoDTO
{
public string Photo { get; set; }
public string Title { get; set; }
}
At first sight, there’s nothing wrong with this code. You’d say when the form is posted, the PhotoDTO object gets automatically created by the default modelbinder in the framework, and you’ll be able to do what you want with the PhotoDTO (like, errr, save it?). However, what REALLY happens is that the parameter photo will be null. Now I’ll give you a moment to realize what’s happening.
…
…
Alright, that’s enough. What’s happening is that the field with the name ‘Photo’ is getting precedence over binding the whole thing to the PhotoDTO class. So let’s say I put the value “SomePhoto” in the textbox, it’ll try to bind that value to an object of the type PhotoDTO. That fails, so it returns null.
I’m not sure it’s intended, I’m assuming it’s just a side-effect of what needs to be done to be able to bind to complex models as well as simple parameters. Either way, if you’re not aware of this quirk you’re in for a surprise if you accidentally run into this!
The conclusion
I asked Phil Haack on twitter if this was intended. He said:
@erikvanbrakel yes, by design. BTW, your PHotoDTO needs to make properties public too.
So there you have it, keep this in mind when writing your code, it’s not going anywhere, it’s as intended!
Note: I corrected the PhotoDTO, it was missing the ‘public’ access specifiers.