for a project, I need a way to specify whether or not a property has changed.
So in a model I would like the following:
public class Changeable<T>
{
public bool Changed { get; set; }
public T Value { get; set; }
}
public class MyModel
{
[Range(1, 10)]
public Changeable<int> SomeInt { get; set; }
}
View:
@Html.EditorFor(model => model.SomeInt)
And then I would generate a editor with a textfield (the int) and a checkbox (is changed).
The validation attributes (Range
etc.) should be invoked when the checkbox is checked but not when it is unchecked.
I have tried to make the above with an editortemplate for Changeable
(and then comes the validation, model binding etc.) but I'm already lost by the editortemplate because it can't be generic.
Is the solution I want possible, or is there another reasonalble elegant solution?
Right now I'm developing a solution with a property string[] ChangedProperties
and a lot of Javascript to handle validation etc. but it's rather ugly and far from done.
Thanks...
I'm not 100% sure, but I think what you want is:
You may try using dynamic types with a custom range validation attribute:
then a controller:
then a view (
~/Views/Home/Index.cshtml
):and the corresponding editor template (notice the name of the editor template file)
I was fascinated by this question, and I spent a fair amount of time thinking about your goals. I had a breakthrough yesterday, and I have some code which accomplishes almost all of your objectives.
You had said that you wanted the validators to fire only when
Changed
was checked. This code always fires the validators, as I do not believe it is a good practice to prevent validators from firing. What the code does instead is to check to see if the user has changed the value, and it automatically checksChanged
when this happens. If the user unchecks the Changed checkbox, the old value is placed in theValue
box.The code consists of an HTML helper, a ModelMetadataProvider, a ModelBinder, and just a little javascript. Before the code, here is the defined model, which is the same as Darin's, with one additional property added:
Starting with the HTML helper:
This passes the parent metadata into the
ViewData
(which will permit us to get the class validators later on). It also creates lambda expressions so we can useCheckBoxFor()
andEditorFor()
. The view using our model and this helper is as follows:Note the javascript for dealing with changes to the Value textbox and clicks on the Changed checkbox. Also note the need to pass the
Changeable<T>
property twice to theChangeableFor()
helper.Next, the custom ModelValidatorProvider:
Note that there are different means of checking for the parent metadata, depending on whether we are populating a view or binding a model on a POST. Also note that we need to suppress the parent from receiving the validators.
Finally, the ModelBinder:
This takes the parent metadata, and stashes it away, to be accessed later in the custom ModelValidatorProvider.
Finish up with the following in
Application_Start
in Global.asax.cs:Viola!