mirror of https://github.com/abpframework/abp.git
committed by
GitHub
5 changed files with 192 additions and 5 deletions
@ -0,0 +1,34 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; |
|||
using Microsoft.Extensions.Localization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.DataAnnotations; |
|||
|
|||
public class EnumDataTypeAttributeAdapter : AttributeAdapterBase<EnumDataTypeAttribute> |
|||
{ |
|||
public EnumDataTypeAttributeAdapter( |
|||
EnumDataTypeAttribute attribute, |
|||
IStringLocalizer? stringLocalizer) |
|||
: base(attribute, stringLocalizer) |
|||
{ |
|||
} |
|||
|
|||
public override void AddValidation(ClientModelValidationContext context) |
|||
{ |
|||
Check.NotNull(context, nameof(context)); |
|||
|
|||
//There is no built-in client side validation rule for enum values.
|
|||
//This adapter is used to localize the error message on the server side.
|
|||
} |
|||
|
|||
public override string GetErrorMessage(ModelValidationContextBase validationContext) |
|||
{ |
|||
Check.NotNull(validationContext, nameof(validationContext)); |
|||
|
|||
return GetErrorMessage( |
|||
validationContext.ModelMetadata, |
|||
validationContext.ModelMetadata.GetDisplayName() |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; |
|||
using Microsoft.Extensions.Localization; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.DataAnnotations; |
|||
|
|||
public class AbpValidationAttributeAdapterProvider_Tests |
|||
{ |
|||
private readonly AbpValidationAttributeAdapterProvider _provider = new(new ValidationAttributeAdapterProvider()); |
|||
|
|||
[Fact] |
|||
public void Should_Return_An_Adapter_For_The_EnumDataTypeAttribute() |
|||
{ |
|||
//ASP.NET Core does not provide an adapter for the EnumDataTypeAttribute.
|
|||
new ValidationAttributeAdapterProvider() |
|||
.GetAttributeAdapter(new EnumDataTypeAttribute(typeof(MyEnum)), null) |
|||
.ShouldBeNull(); |
|||
|
|||
_provider.GetAttributeAdapter(new EnumDataTypeAttribute(typeof(MyEnum)), null) |
|||
.ShouldBeOfType<EnumDataTypeAttributeAdapter>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Localize_The_Error_Message_Of_The_EnumDataTypeAttribute() |
|||
{ |
|||
var attribute = new EnumDataTypeAttribute(typeof(MyEnum)) { ErrorMessage = "MyEnumIsInvalid" }; |
|||
|
|||
var adapter = _provider.GetAttributeAdapter(attribute, new TestStringLocalizer())!; |
|||
|
|||
adapter.GetErrorMessage(CreateValidationContext()).ShouldBe("Localized:MyEnumIsInvalid"); |
|||
} |
|||
|
|||
private static ModelValidationContextBase CreateValidationContext() |
|||
{ |
|||
var metadataProvider = new EmptyModelMetadataProvider(); |
|||
|
|||
return new ClientModelValidationContext( |
|||
new ActionContext(), |
|||
metadataProvider.GetMetadataForProperty(typeof(MyModel), nameof(MyModel.Value)), |
|||
metadataProvider, |
|||
new Dictionary<string, string>() |
|||
); |
|||
} |
|||
|
|||
public enum MyEnum |
|||
{ |
|||
Value1 = 1 |
|||
} |
|||
|
|||
public class MyModel |
|||
{ |
|||
public MyEnum Value { get; set; } |
|||
} |
|||
|
|||
private class TestStringLocalizer : IStringLocalizer |
|||
{ |
|||
public LocalizedString this[string name] => new(name, "Localized:" + name); |
|||
|
|||
public LocalizedString this[string name, params object[] arguments] => new(name, "Localized:" + name); |
|||
|
|||
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) |
|||
{ |
|||
return new List<LocalizedString>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.Testing; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Uow; |
|||
|
|||
public class UnitOfWork_Child_Events_Tests : AbpIntegratedTest<AbpUnitOfWorkModule> |
|||
{ |
|||
private readonly IUnitOfWorkManager _unitOfWorkManager; |
|||
|
|||
public UnitOfWork_Child_Events_Tests() |
|||
{ |
|||
_unitOfWorkManager = ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Child_UnitOfWorks_Should_Not_Accumulate_Event_Handlers_On_The_Parent() |
|||
{ |
|||
using (var parentUow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
var failedHandlerCount = GetEventHandlerCount(parentUow, nameof(IUnitOfWork.Failed)); |
|||
var disposedHandlerCount = GetEventHandlerCount(parentUow, nameof(IUnitOfWork.Disposed)); |
|||
|
|||
for (var i = 0; i < 100; i++) |
|||
{ |
|||
using (var childUow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
childUow.Id.ShouldBe(parentUow.Id); //It's a child of the parent UOW.
|
|||
} |
|||
} |
|||
|
|||
//Disposed child UOWs should not leave any handler behind on the parent.
|
|||
GetEventHandlerCount(parentUow, nameof(IUnitOfWork.Failed)).ShouldBe(failedHandlerCount); |
|||
GetEventHandlerCount(parentUow, nameof(IUnitOfWork.Disposed)).ShouldBe(disposedHandlerCount); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Trigger_Disposed_Event_Subscribed_Over_A_Child_UnitOfWork() |
|||
{ |
|||
var disposed = false; |
|||
|
|||
using (var parentUow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
using (var childUow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
childUow.Disposed += (sender, args) => disposed = true; |
|||
} |
|||
|
|||
disposed.ShouldBeFalse(); //The parent UOW has not been disposed yet!
|
|||
} |
|||
|
|||
disposed.ShouldBeTrue(); |
|||
} |
|||
|
|||
private static int GetEventHandlerCount(IUnitOfWork unitOfWork, string eventName) |
|||
{ |
|||
var field = unitOfWork.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic); |
|||
field.ShouldNotBeNull(); |
|||
|
|||
return field.GetValue(unitOfWork) is Delegate handler |
|||
? handler.GetInvocationList().Length |
|||
: 0; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue