I recently found that if i said:
object latestPosts = new MyApp.Models.LatestPosts();
TryUpdateModel(latestPosts);
The latestPosts object does not update. This is due to an issue found here. Using the workaround solved the issue. However if i move latestPosts to be a property (called Parameters) of an existing type (e.g. Widget) it doesn’t update the model. E.g.
var widget = new Widget();
MyTryUpdateModel(widget, "Widget", null, null, ValueProvider); // LatestPosts doesn't update
But the following does work:
MyTryUpdateModel(widget.Parameters, "Widget.Parameters", null, null, ValueProvider);
Edit: Here’s the Widget class:
public class Widget {
[Required, StringLength(100)]
public virtual string Name { get; set; }
private object _parameters;
public virtual object Parameters {
get {
// Code removed for brevity
if (_parameters == null)
_parameters = new MyApp.Models.LatestPosts();
return _parameters;
} set { _parameters = value; }
}
}
And here’s the LatestPosts class:
public class LatestPosts {
public int NumPosts { get; set; }
}
I can’t see why the initial MyTryUpdateModel didn’t work for updating the whole of the Widget since it should handle complex types. I’d appreciate it if someone could shed some light on this issue.
Thanks
I will explaim both why the original TryUpdateModel doesn’t work and why the “patched TryUpdateNode doesn’t work in your case. I am the coordinator of the Mvc Controls Toolkit that contains a complex custom Model Binder, so we acquired a deep knowledge of Model Binder and of the problems behind it.
Default TryUpdateModel: it just invoke the DefaultModelBinder. Now determining the type at runtime based on information gained during the model binding process is risky, because such information come from the client and might be manipulated by a malicious user that, this way, might force the model binder to create an instance of a Type he decided….very risky…He might exploit this to force model binder to execute unwanted malicious code that is in the constructor of the “fake” type. So the general design choice is that ALL TYPES used by the model binder MUST BE DETERMINED AT COMPILE TIME
MyTryUpdateModel: it just determine the type of the root model by calling GetType, and then use this information to invoke the default model binder on this type. However, with the exception of this initia “startup” the Model Binder works as usual ….that is…the type of the properties of the root model, IS NOT OBTAINED WITH GetType or with runtime infos, but by just inspecting the type of the property of the root model…that in your case is object…that means no information.
The defaul custom model binder of the Mvc Controls Toolkit has tools for determining the type at runtime…but not ALL TYPES..because thi expose at risks of attcks…types that are subtypes of “safe” types..for instance types that implement an Interface.