Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,24 @@ public FluentValidationHtmlConventions(IValidatorFinder validatorFinder, FluentV
public static string GetMessage(RequestData requestData, PropertyValidatorResult propertyValidator)
{
MessageFormatter formatter = new MessageFormatter().AppendPropertyName(propertyValidator.DisplayName);
string message = formatter.BuildMessage(propertyValidator.PropertyValidator.Options.GetErrorMessageTemplate(null));
string message = formatter.BuildMessage(propertyValidator.PropertyValidator.GetDefaultMessageTemplate(null));
return message;
}

public void AddEqualToDataAttr(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData request)
{
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is EqualValidator);
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is IEqualValidator);
if (result != null)
{
var equal = result.PropertyValidator as EqualValidator;
var equal = result.PropertyValidator as IEqualValidator;

if (equal.MemberToCompare != null)
{
MessageFormatter formatter = new MessageFormatter()
.AppendPropertyName(result.DisplayName)
.AppendArgument("ComparisonValue", equal.MemberToCompare.Name);

string message = formatter.BuildMessage(equal.Options.GetErrorMessageTemplate(null));
string message = formatter.BuildMessage(equal.GetDefaultMessageTemplate(null));

htmlTag.Data("val", true);
htmlTag.Data("val-equalto", message);
Expand All @@ -67,8 +67,7 @@ public void AddEqualToDataAttr(IEnumerable<PropertyValidatorResult> propertyVali

public void AddRequiredClass(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData requestData)
{
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is NotEmptyValidator
|| x.PropertyValidator is NotNullValidator);
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is INotEmptyValidator or INotNullValidator);

if (result != null)
{
Expand All @@ -78,16 +77,16 @@ public void AddRequiredClass(IEnumerable<PropertyValidatorResult> propertyValida

public void AddLengthClasses(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData requestData)
{
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is LengthValidator);
if (result != null)
var lengthValidator = propertyValidators.Select(x => x.PropertyValidator).OfType<ILengthValidator>().FirstOrDefault();
if (lengthValidator != null)
{
htmlTag.Attr("maxlength", ((LengthValidator)result.PropertyValidator).Max);
htmlTag.Attr("maxlength", lengthValidator.Max);
}
}

public void AddCreditCardClass(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData requestData)
{
var lengthValidator = propertyValidators.Select(x => x.PropertyValidator).OfType<CreditCardValidator>().FirstOrDefault();
var lengthValidator = propertyValidators.Select(x => x.PropertyValidator).OfType<ICreditCardValidator>().FirstOrDefault();
if (lengthValidator != null)
{
//if (!_msUnobtrusive)
Expand All @@ -99,21 +98,19 @@ public void AddCreditCardClass(IEnumerable<PropertyValidatorResult> propertyVali

public void AddRegexData(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData requestData)
{
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is RegularExpressionValidator);
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is IRegularExpressionValidator);

if (result != null)
{
var regex = result.PropertyValidator as RegularExpressionValidator;
var regex = (IRegularExpressionValidator)result.PropertyValidator;
var msg = GetMessage(requestData, result) ?? string.Format("The value did not match the regular expression '{0}'", regex.Expression);
htmlTag.Data("val", true).Data("val-regex", msg).Data("val-regex-pattern", regex.Expression);
}
}

public void AddEmailData(IEnumerable<PropertyValidatorResult> propertyValidators, HtmlTag htmlTag, RequestData requestData)
{
#pragma warning disable 618
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is EmailValidator);
#pragma warning restore 618
var result = propertyValidators.FirstOrDefault(x => x.PropertyValidator is IEmailValidator);
if (result != null)
{
var msg = GetMessage(requestData, result) ?? string.Format("The value is not a valid email address");
Expand Down
37 changes: 17 additions & 20 deletions src/SchoStack.AspNetCore.FluentValidation/FluentValidatorFinder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentValidation;
using FluentValidation.Validators;
Expand All @@ -27,11 +26,11 @@ public FluentValidatorFinder(Func<Type, IValidator> resolver)
public IEnumerable<PropertyValidatorResult> FindValidators(RequestData requestData)
{
if (requestData.InputType == null)
return new List<PropertyValidatorResult>();
return Array.Empty<PropertyValidatorResult>();

var baseValidator = ResolveValidator(requestData.InputType);
if (baseValidator == null)
return new List<PropertyValidatorResult>();
return Array.Empty<PropertyValidatorResult>();

var properties = InputPropertyMatcher.FindPropertyData(requestData);
var validators = GetPropertyValidators(baseValidator, properties);
Expand All @@ -41,49 +40,47 @@ public IEnumerable<PropertyValidatorResult> FindValidators(RequestData requestDa
private IEnumerable<PropertyValidatorResult> GetPropertyValidators(IValidator baseValidator, List<PropertyInfo> properties)
{
var desc = baseValidator.CreateDescriptor();
var validators = GetNestedPropertyValidators(desc, properties, 0).ToList();
var validators = GetNestedPropertyValidators(desc, properties, 0);
return validators;
}

private IEnumerable<PropertyValidatorResult> GetNestedPropertyValidators(IValidatorDescriptor desc, List<PropertyInfo> propertyInfo, int i)
{
if (i == propertyInfo.Count)
return new List<PropertyValidatorResult>();
yield break;

var vals = desc.GetValidatorsForMember(propertyInfo[i].Name);
var name = desc.GetName(propertyInfo[i].Name);

var propertyValidators = new List<PropertyValidatorResult>();

foreach (var inlineval in vals)
foreach ((dynamic inlineval, _) in vals)
{
if (i == propertyInfo.Count - 1)
{
propertyValidators.Add(new PropertyValidatorResult(inlineval, name));
yield return new PropertyValidatorResult(inlineval, name);
}
var val = GetValidator(inlineval);

IValidator val = GetValidator(inlineval);
if (val == null)
continue;

var nestedPropertyValidators = GetNestedPropertyValidators(val.CreateDescriptor(), propertyInfo, i + 1);
propertyValidators.AddRange(nestedPropertyValidators.Select(x => new PropertyValidatorResult(x.PropertyValidator, x.DisplayName)));
foreach (var validator in nestedPropertyValidators)
{
yield return validator;
}
}

return propertyValidators;
}

private IValidator GetChildValidator(IChildValidatorAdaptor adaptor)
private static IValidator GetChildValidator<T>(IChildValidatorAdaptor adaptor)
{
var validatorContext = new ValidationContext<object>(null);
var propertyValidatorContext = new PropertyValidatorContext(validatorContext, null, null, null);
return ((dynamic) adaptor).GetValidator(propertyValidatorContext);
var validatorContext = new ValidationContext<T>(default);
return ((dynamic)adaptor).GetValidator(validatorContext, null);
}

private IValidator GetValidator(IPropertyValidator propertyValidator)
private static IValidator GetValidator<T, TProperty>(PropertyValidator<T, TProperty> propertyValidator)
{
if (propertyValidator is IChildValidatorAdaptor child)
return GetChildValidator(child);
return GetChildValidator<T>(child);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand All @@ -13,16 +13,12 @@
<IsPackable>true</IsPackable>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<LangVersion>7.1</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>7.1</LangVersion>
<PropertyGroup>
<LangVersion>9</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentValidation.AspNetCore" Version="9.3.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.*" />
<PackageReference Include="htmltags.aspnetcore" Version="7.0.4" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" PrivateAssets="All" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand All @@ -22,7 +22,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" PrivateAssets="All" />
</ItemGroup>

Expand Down
32 changes: 13 additions & 19 deletions src/SchoStack.AspNetCore.Sample/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Linq;
using System.Threading.Tasks;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -19,7 +19,6 @@
using FluentValidation;
using FluentValidation.Results;
using FluentValidation.Validators;
using HtmlTags.Reflection;
using SchoStack.AspNetCore.FluentValidation;
using SchoStack.AspNetCore.HtmlConventions.Core;

Expand Down Expand Up @@ -98,7 +97,7 @@ public async Task<IActionResult> About(AboutInputModel input) => await _actionBu
.For(input)
.BeforeSend(async (_, c) =>
{
c.ActionContext.HttpContext.Response.Headers.Add("X-Test", "test");
c.ActionContext.HttpContext.Response.Headers.Append("X-Test", "test");
await Task.CompletedTask;
})
.Error(async () => await About(new AboutQueryModel()))
Expand Down Expand Up @@ -218,7 +217,7 @@ public class AboutViewModelValidator : AbstractValidator<AboutViewModel>
{
public AboutViewModelValidator()
{
RuleFor(x => x.Name).SetValidator(new NameValidator());
RuleFor(x => x.Name).SetValidator(new NameValidator<AboutViewModel>());
RuleFor(x => x.NestedModel).SetValidator(new NestedModelValidator());
}
}
Expand All @@ -231,26 +230,21 @@ public NestedModelValidator()
}
}

public class NameValidator : IPropertyValidator
public class NameValidator<TModel> : IPropertyValidator<TModel,string>
{
public IEnumerable<ValidationFailure> Validate(PropertyValidatorContext context)
public string Name => nameof(NameValidator<TModel>);

public string GetDefaultMessageTemplate(string errorCode) => "The Error";

public bool IsValid(ValidationContext<TModel> context, string value)
{
if (!(context.InstanceToValidate is string s) || s != "Name")
if (value != "Name")
{
yield return new ValidationFailure(context.PropertyName, "The Error");
context.AddFailure(new ValidationFailure(context.PropertyName, "The Error"));
return false;
}
}

public Task<IEnumerable<ValidationFailure>> ValidateAsync(PropertyValidatorContext context, CancellationToken cancellation)
{
return Task.FromResult(Validate(context));
}

public bool ShouldValidateAsynchronously(IValidationContext context)
{
return false;
return true;
}

public PropertyValidatorOptions Options { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand Down