Custom error format for fluent validation error - c#

I followed Fluent documentation and I haven't found any option to overwrite default error format that is something like "'{propertyName}' must be something.". I have many validators and I won't rewrite them to .WithMessage("...").
Is there any option to change default message format?
I would like to have a similar interface to PropertyNameResolver that offers smart interface to change property name.

You can overwrite the messages globally by modifying the ValidatorOptions.ResourceProviderType as noted on the localization page.
You only have to define the strings that you would like to change as it will use the default string if no override is specified.

Related

Swagger spec's validation overriding FluentValidation

I am having the following problem, and so far haven't been able to find an effective solution for it. I have the following code in my Swagger spec:
SomeRequest:
type: object
properties:
client_date_of_birth:
type: string
format: date
example: "2021-09-17"
required:
- client_date_of_birth
This of course works fine, but the problem is introduced when I try to use FluentValidation instead of this approach. My FluentValidation code looks like this:
.RuleFor(i => i.ClientDateOfBirth)
.NotEmpty().WithMessage("Client's Date of Birth is empty")
.InclusiveBetween(new LocalDate(1870, 01, 01), todayDate);
I wish to display the FluentValidation message instead of the generic one from Swagger, but so far I haven't found a good way to do this.
If I remove client_date_of_birth as a required field, I will also open up the API's contract to allow this field as a null value (which I want to deal with at API level, not FluentValidation level) and if I set it up as a string instead of a date, I will also be opening up the API's contract to potentially unwanted behavior. Is there a way to override this particular behavior of Swagger with the FluentValidation's implementation?
Just as a clarification: I know I will get the FluentValidation error message if I remove the client_date_of_birth as a required field in the Swagger spec. My question is more about: can I override Swagger's behavior with FluentValidation's? the reason I want to keep it in both places is so the rules of the API's contract are transparent and written in the spec itself, rather than obscure and hidden in the code, even if I will be eventually using said code.

FluentValidation : set a default value on error

I'm trying to set a default value to a field with FluentValidation when the provided value is invalid (ex: if the provided language isn't supported, put an error message and default the language to english). I know it's not a good practice to change a value in a validation but in the case of language, I need it to be properly set for further validations and to display the error messages.
How can I do that ?
Thanks
You can't do this within a fluent validation validator. The validator class should only be concerned with providing validation: this is its single responsibility.
To do what you describe, you could perform the validation and then check for the language related error at which point you could set the default value.
Or perhaps you could default the language value prior to validation - it's difficult to make a recommendation without any code.

fluentvalidation change default error message for int/long

Is there a way to change the default error message for an in in FluentValidation?
We are able to set up validations for more complex types but the simple 'the data you entered isn't an int' style things we can't seem to get at.
The built in error for these is: 'the value x isn't valid for y' or something along those lines - is there a way to override these?
There's no easy/clean way to achieve that. The first possibility is to override the DefaultModelBinder.ResourceClassKey property in your application start and point it to a custom resource file:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
DefaultModelBinder.ResourceClassKey = "Messages";
}
and then define the key PropertyValueInvalid inside App_GlobalResources/Messages.resx.
Another possibility is to use a backing field on your view model as suggested by Jeremy Skinner.
The reason for this is that this error message is generated by the default model binder before any validation can occur on the field. Before you can validate the field it must first be assigned a value. And since you are attempting to convert a string which doesn't represent a valid integer into an integer during model binding, the default model binder assigns a default message.
You can override that as well.
Follow the below link
http://fluentvalidation.codeplex.com/wikipage?title=Customising

Dynamic form validation - emulation of RegularExpressionAttribute in CustomMetadataProvider

My task is to perform validation on form which fields are constructed dynamically(upon database query). I would like to use data annotations. While model is dynamic I can't decorate properties with annotations, but I can use custom metadata provider for example inheriting from DataAnnotationsModelMetadataProvider.
Simply in global.asax at Application_start I supplied my own MetaDataProvider:
ModelMetadataProviders.Current = new MetadataProvider.CustomModelMetadataProvider();
I made a little hack, cause ModelMetadataProviders.Current is per application, my problem needed serving different metadata in each request, but it was not so hard.
This work fine for emulating IsRequired attribute, because metadata provider uses System.Web.Mvc.ModelMetadata and there is IsRequired property , but there is no property such as RegularExpression or anything similar.
So I run debugger and looked at ModelMetadata returned by original DataAnnotationsModelMetadataProvider for property with RegularExpression attribute, and I hadn't found regular expression there anyway.
I would love to get some hints on that.
I figured answer (by inspecting MVC 3 source code) which is as follows:
create custom ModelValidatorProvider for example inheriting from DataAnnotationsModelValidatorProvider
override GetValidators method
add yout custom provider to ModelValidatorProviders.Providers collection
GetValidators method returns IEnumerable<ModelValidator> so its enough to return RegularExpressionAttributeAdapter which inhertis from ModelValidator.

How would one write an Attribute that would set the default value of an auto-property

I've read the post for setting default properties via an attribute, which end with DefaultValue is for Design Mode or Serialization.
BUT, is there a way to write an Attribute that will do what these posts require: default the property to some value.
If there is a way -- how would one start writing such an attribute?
Thanks,
L-
You can't, basically.
You can set the default in the constructor, though.
As it happens I did implement something that did this very recently, but that was using factory-based construction; the factory checked for [DefaultValue] and set the value via reflection. But attributes can't cause arbitrary code execution unless you use a re-writer like PostSharp.
If the constructor is too far away for your liking, you will have to use a field-initializer and write the get/set against the field.
Unfortunately attributes are just metadata, meaning they cannot run or do something on their own.
However nothing prevents you from writing an extension method with a name like SetDefaultValues that reads default values from attributes and assigns them to properties.
I've done a similar thing in a recent project, and it proved to be a good decision because it kept all default values defined in a declarative style in a single place.
There is an interesting article on CodeProject peering into different strategies for implementation of [DefaultValue]-based initialization and comparing their performance. I suggest you check it out.

Categories