There are some properties in my view model that are optional when saving, but required when submitting. In a word, we allow partial saving, but the whole form is submitted, we do want to make sure all required fields have values.
The only approaches I can think of at this moment are:
The view model has all [Required]
attributes in place. If the request is partial save, the ModelState.IsValid
becomes false
when entering the controller action. Then I run through all ModelState
(which is an ICollection<KeyValuePair<string, ModelState>>
) errors and remove all errors raised by [Required]
properties.
But if the request is to submit the whole form, I will not interfere with the ModelState
and the [Required]
attributes take effect.
This one is even more ugly. One view model will contain all the [Required]
attributes, used by an action method for submitting. But for partial save, I post the form data to a different action which use a same view model without all the [Required]
attributes.
Obviously, I would end up with a lot of duplicate code / view models.
I have been thinking if I can create a custom data annotation attribute [SubmitRequired]
for those required properties. And somehow make the validation ignores it when partial saving but not when submitting.
Still couldn't have a clear clue. Anyone can help? Thanks.
This is one approach I use in projects.
Create a ValidationService<T>
containing the business logic that will check that your model is in a valid state to be submitted with a IsValidForSubmission
method.
Add an IsSubmitting
property to the view model which you check before calling the IsValidForSubmission
method.
Only use the built in validation attributes for checking for invalid data i.e. field lengths etc.
Create some custom attributes within a different namespace that would validate in certain scenarios i.e. [RequiredIfSubmitting]
and then use reflection within your service to iterate over the attributes on each property and call their IsValid
method manually (skipping any that are not within your namespace).
This will populate and return a Dictionary<string, string>
which can be used to populate ModelState
back to the UI:
var validationErrors = _validationService.IsValidForSubmission(model);
if (validationErrors.Count > 0)
{
foreach (var error in validationErrors)
{
ModelState.AddModelError(error.Key, error.Value);
}
}
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