I want to model an 'Expense' object that has a 'Sum' (decimal) field. In the view, I want to validate that the user enters a positive value.
OTOH I want to make sure I save the object with a negative value in the DB.
Right now, the model looks like this:
//------The model-------
public class Operation {
[Range(typeof(decimal), "0.0001", "79228162514264337593543950335")]
public virtual decimal Sum { get; set; }
[...]
}
public class Expense : Operation
{
public override decimal Sum
{
get
{
return base.Sum;
}
set
{
base.Sum = - Math.Abs(value);
}
}
}
//------In the controller-------
[HttpPost]
public ActionResult CreateExpense(Expense operation, int[] SelectedTags)
{
return CreatePost(operation, SelectedTags);
}
private ActionResult CreatePost(Operation operation, int[] SelectedTags)
{
if (ModelState.IsValid) // <-- this fails
[...]
}
The problem is, the MVC validation works with the object's properties (not the POST'ed form values), sees the negative value and fails to validate.
What should I do to fix this?
It looks to me like I'm not separating concerns (validate user input vs maintain database integrity).
Should I use a view model to hold the user input and then populate the actual model from the view model? Doesn't sound like KISS...
I found out that specifying a separate validation attribute on the property of the inherited class works a treat.
Can't think of something more straight-forward.
Here's how the model looks like now:
public class Operation {
public virtual decimal Sum { get; set; }
}
public class Income : Operation
{
[Range(typeof(decimal), "0.0001", "79228162514264337593543950335")]
public override decimal Sum
{
get { return base.Sum; }
set { base.Sum = Math.Abs(value); }
}
}
public class Expense : Operation
{
[Range(typeof(decimal), "-79228162514264337593543950335", "-0.0001")]
public override decimal Sum
{
get { return base.Sum; }
set { base.Sum = - Math.Abs(value); }
}
}