Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change to handling DateTime in LessThanOrEqualTo #1721

Closed
jt-pt-dev opened this issue Apr 28, 2021 · 4 comments
Closed

Change to handling DateTime in LessThanOrEqualTo #1721

jt-pt-dev opened this issue Apr 28, 2021 · 4 comments
Milestone

Comments

@jt-pt-dev
Copy link

FluentValidation version

10.0.4

ASP.NET version

.NET 5

Summary

There appears to be a difference in the LessThanOrEqualTo handling client-side (in my case for DateTime) going from 9.5.4 to 10.0.4. This is causing client-side validation to incorrectly fail for valid cases.

I have read through the upgrade guide and the only change made was going from services.AddTransient to services.AddScoped.

Leaving the services.AddScoped in place and simply flipping the package version back and forth reproduces the issue.

Steps to Reproduce

The validators are checking that the start date is before the end date:

RuleFor(v => v.startDate)
	.NotEmpty()
	.LessThanOrEqualTo(v => v.endDate));

RuleFor(v => v.endDate)
	.NotEmpty());

The HTML/Razor is:

<div class="form-group" required>
	<label asp-for="query.startDate" class="required-label">Start date</label>
	<input asp-for="query.startDate" class="form-control" type="date" />
	<span asp-validation-for="query.startDate"></span>
</div>

The input field for the start date changes but all other HTML remains the same.

The resultant HTML for 9.5.4 is:

<input class="form-control" type="date" data-val="true" data-val-required="&#x27;Start date&#x27; must not be empty." id="query_startDate" name="query.startDate" value="2021-03-28" />

The resultant HTML for 10.0.4 is:

<input class="form-control" type="date" data-val="true" data-val-range="End date must be after Start date." data-val-range-max="01/01/0001 00:00:00" data-val-range-min="0" data-val-required="&#x27;Start date&#x27; must not be empty." id="query_startDate" name="query.startDate" value="2021-03-28" />

This change causes client-side validation to fail with a message that 'End date must be after Start date.' with a value of 28/03/201 for start and 28/04/2021 for the end date.

@JeremySkinner
Copy link
Member

Hi, thanks for reporting this. It looks like the call to LessThan is emitting the wrong clientside metadata.

FluentValidation doesn’t perform clientside validation directly but rather exports metadata which is then used by asp.net to generate the markup and perform clientside validation.

Asp.net doesn’t have clientside validator equivalents for GreaterThan/LessThan, so FluentValidation shouldn’t emit clientside metadata for these, so I think this is a bug where metadata is being exported for the wrong thing, from the markup it looks like it’s generating markup for Range validation (which should only be triggered for InxlusiveBetween).

I’ll have a look at what’s going on and try and get this fixed today.

@jt-pt-dev
Copy link
Author

Awesome. Thank you.

JeremySkinner added a commit that referenced this issue Apr 28, 2021
@JeremySkinner
Copy link
Member

This is fixed, and I've pushed out the 10.1 release to nuget. Please give it a try and let me know if you run into any further issues.

Some background if you're interested: the LessThanOrEqual validator actually should generate clientside metadata, but only if compared to a constant value (eg RuleFor(x => x.Foo).LessThanOrEqual(10) should generate data-val-min="0" data-val-max="10". However this shouldn't be generated when performing a cross-property check (RuleFor(x => x.Foo).LessThanOrEqual(x => x.Bar)

Internally, the LessThanOrEqual validator stores the value it's being compared against. In 9.x, this was stored as type object, but in 10.x all our internal API is generic so is instead of type TProperty (which resolves directly to DateTime). Because DateTimes are non-nullable value types, the comparison value is generated as default(DateTime) which is 01/01/0001 00:00:00 rather than null, which ended up triggering the generation of clientside metadata.

@JeremySkinner JeremySkinner added this to the 10.1 milestone Apr 28, 2021
@jt-pt-dev
Copy link
Author

That has fixed the problem. Thanks.

The explanation is definitely interesting. It gives an insight in to what is happening 'under the covers'. Very cool.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants