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