Hi Jeremy,
The FluentValidationModelValidatorProvider integration with MVC is very useful. However, if one would like to override some parts of the class it is not possible since the only overridable function is GetValidators.
In particular, it would be interesting to be able to access the (currently) private method IsValidatingProperty and create a new method that invokes the validator factory, which can be overriden.
Rationale: The type passed to the validator factory may not be always correct in order to make the best decision for a validator. In other words, ModelMetadata.ContainerType or ModelMetadata.ModelType (depending on wether a property or the model is being validated) may not be the correct type to use.
For example, suppose the following form models:
```
class F1 {
int Property {get; set;}
}
class F2 : F1 {
int Another { get; set; }
}
```
Each with its own validator. Now suppose I have a partial view that renders the appropriate way to select Property (involving a `TextBoxFor(f => f.Property)`, and it is strongly typed to F1. This partial will be called from a strongly typed view of F2.
In this scenario, when the `TextBoxFor(f => f.Property)` is rendered, the ModelMetadata.ContainerType will be F1 instead of F2, thus rendering the wrong unobtrusive validations.
Summary: an overridable function that determines which type to pass to the validator factory would be nice to have in the Provider.
The following code should provide everything needed.
````
public virtual IValidator InvokeValidatorFactory(ModelMetadata metadata,
ControllerContext context) {
if (IsValidatingProperty(metadata)) {
return ValidatorFactory.GetValidator(metadata.ContainerType);
}
return ValidatorFactory.GetValidator(metadata.ModelType);
}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata,
ControllerContext context) {
IValidator validator = InvokeValidatorFactory(metadata, context);
if (IsValidatingProperty(metadata)) {
return GetValidatorsForProperty(metadata, context, validator);
}
return GetValidatorsForModel(metadata, context, validator);
}
````
Comments: I've implemented this in the latest commit (although I called the method "CreateValidator" rather than "InvokeValidatorFactory" for consistency with other areas of the codebase). Please give this a try and let me know if this works for you. Jeremy
The FluentValidationModelValidatorProvider integration with MVC is very useful. However, if one would like to override some parts of the class it is not possible since the only overridable function is GetValidators.
In particular, it would be interesting to be able to access the (currently) private method IsValidatingProperty and create a new method that invokes the validator factory, which can be overriden.
Rationale: The type passed to the validator factory may not be always correct in order to make the best decision for a validator. In other words, ModelMetadata.ContainerType or ModelMetadata.ModelType (depending on wether a property or the model is being validated) may not be the correct type to use.
For example, suppose the following form models:
```
class F1 {
int Property {get; set;}
}
class F2 : F1 {
int Another { get; set; }
}
```
Each with its own validator. Now suppose I have a partial view that renders the appropriate way to select Property (involving a `TextBoxFor(f => f.Property)`, and it is strongly typed to F1. This partial will be called from a strongly typed view of F2.
In this scenario, when the `TextBoxFor(f => f.Property)` is rendered, the ModelMetadata.ContainerType will be F1 instead of F2, thus rendering the wrong unobtrusive validations.
Summary: an overridable function that determines which type to pass to the validator factory would be nice to have in the Provider.
The following code should provide everything needed.
````
public virtual IValidator InvokeValidatorFactory(ModelMetadata metadata,
ControllerContext context) {
if (IsValidatingProperty(metadata)) {
return ValidatorFactory.GetValidator(metadata.ContainerType);
}
return ValidatorFactory.GetValidator(metadata.ModelType);
}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata,
ControllerContext context) {
IValidator validator = InvokeValidatorFactory(metadata, context);
if (IsValidatingProperty(metadata)) {
return GetValidatorsForProperty(metadata, context, validator);
}
return GetValidatorsForModel(metadata, context, validator);
}
````
Comments: I've implemented this in the latest commit (although I called the method "CreateValidator" rather than "InvokeValidatorFactory" for consistency with other areas of the codebase). Please give this a try and let me know if this works for you. Jeremy