Skip to content

Commit

Permalink
Merge pull request #4524 from abpframework/Cotur/dynamic-max-length
Browse files Browse the repository at this point in the history
Introduced DynamicMaxLength
  • Loading branch information
hikalkan authored Jun 29, 2020
2 parents c1fd463 + 2d4f89b commit c401ce5
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public virtual IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribu
{
return new DynamicStringLengthAttributeAdapter((DynamicStringLengthAttribute) attribute, stringLocalizer);
}

if (type == typeof(DynamicMaxLengthAttribute))
{
return new DynamicMaxLengthAttributeAdapter((DynamicMaxLengthAttribute) attribute, stringLocalizer);
}

return _defaultAdapter.GetAttributeAdapter(attribute, stringLocalizer);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Globalization;
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Localization;
using Volo.Abp.Validation;

namespace Volo.Abp.AspNetCore.Mvc.DataAnnotations
{
public class DynamicMaxLengthAttributeAdapter : AttributeAdapterBase<DynamicMaxLengthAttribute>
{
private readonly string _max;

public DynamicMaxLengthAttributeAdapter(
DynamicMaxLengthAttribute attribute,
IStringLocalizer stringLocalizer)
: base(attribute, stringLocalizer)
{
_max = Attribute.Length.ToString(CultureInfo.InvariantCulture);
}

public override string GetErrorMessage(ModelValidationContextBase validationContext)
{
Check.NotNull(validationContext, nameof(validationContext));

return GetErrorMessage(
validationContext.ModelMetadata,
validationContext.ModelMetadata.GetDisplayName(),
Attribute.Length
);
}

public override void AddValidation(ClientModelValidationContext context)
{
Check.NotNull(context, nameof(context));

MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-maxlength", GetErrorMessage(context));
MergeAttribute(context.Attributes, "data-val-maxlength-max", _max);

if (Attribute.Length != int.MaxValue)
{
MergeAttribute(context.Attributes, "data-val-maxlength-max", _max);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reflection;
using JetBrains.Annotations;

namespace Volo.Abp.Validation
{
public class DynamicMaxLengthAttribute : MaxLengthAttribute
{
private static readonly FieldInfo MaximumLengthField;

static DynamicMaxLengthAttribute()
{
MaximumLengthField = typeof(MaxLengthAttribute).GetField(
"<Length>k__BackingField",
BindingFlags.Instance | BindingFlags.NonPublic
);
Debug.Assert(MaximumLengthField != null, nameof(MaximumLengthField) + " != null");
}

public DynamicMaxLengthAttribute(
[NotNull] Type sourceType,
[CanBeNull] string maximumLengthPropertyName)
{
Check.NotNull(sourceType, nameof(sourceType));

if (maximumLengthPropertyName != null)
{
var maximumLengthProperty = sourceType.GetProperty(
maximumLengthPropertyName,
BindingFlags.Static | BindingFlags.Public
);
Debug.Assert(maximumLengthProperty != null, nameof(maximumLengthProperty) + " != null");
MaximumLengthField.SetValue(this, (int) maximumLengthProperty.GetValue(null));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,23 @@ public class ValidationTest1Model

public class ValidationDynamicTestModel
{
[DynamicStringLength(typeof(Consts), nameof(Consts.MaxValue2Length), nameof(Consts.MinValue2Length))]
[DynamicStringLength(typeof(Consts), nameof(Consts.MaxValue1Length), nameof(Consts.MinValue1Length))]
public string Value1 { get; set; }

[DynamicMaxLength(typeof(Consts), nameof(Consts.MaxValue2Length))]
public string Value2 { get; set; }

[DynamicMaxLength(typeof(Consts), nameof(Consts.MaxValue3Length))]
public int[] Value3 { get; set; }

public static class Consts
{
public static int MinValue2Length { get; set; } = 2;
public static int MaxValue2Length { get; set; } = 7;
public static int MinValue1Length { get; set; } = 2;
public static int MaxValue1Length { get; set; } = 7;

public static int MaxValue2Length { get; set; } = 4;

public static int MaxValue3Length { get; set; } = 2;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,24 @@ public async Task Should_Return_Custom_Validate_Errors()
[Fact]
public async Task Should_Validate_Dynamic_Length_Object_Result_Success()
{
var result = await GetResponseAsStringAsync("/api/validation-test/object-result-action-dynamic-length?value1=hello");
var result = await GetResponseAsStringAsync("/api/validation-test/object-result-action-dynamic-length?value1=hello&value3[0]=53&value3[1]=54");
result.ShouldBe("hello");

}

[Fact]
public async Task Should_Validate_Dynamic_Length_Object_Result_Failing()
{
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=a", HttpStatusCode.BadRequest); //value1 has min length of 2 chars.
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=a", HttpStatusCode.BadRequest); //value1 has min string length of 2 chars.
result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0);

result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=12345678", HttpStatusCode.BadRequest); //value1 has max string length of 7 chars.
result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0);

result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=123458&value2=12345", HttpStatusCode.BadRequest); //value2 has max length of 5 chars.
result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0);

result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=12345678", HttpStatusCode.BadRequest); //value1 has max length of 7 chars.
result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/validation-test/object-result-action-dynamic-length?value1=123458&value3[0]=53&value3[1]=54&value3[2]=55&value3[3]=56", HttpStatusCode.BadRequest); //value3 has max length of 2.
result.Error.ValidationErrors.Length.ShouldBeGreaterThan(0);
}
}
Expand Down

0 comments on commit c401ce5

Please sign in to comment.