Browse Source

Merge pull request #3348 from abpframework/maliming/Interceptors-ignore-types

Introducing DynamicProxyIgnoreTypes.
pull/3559/head
Halil İbrahim Kalkan 6 years ago
committed by GitHub
parent
commit
c923dfd045
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs
  2. 12
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  3. 13
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  4. 103
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs
  5. 112
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs
  6. 44
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs
  7. 105
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  8. 6
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs
  9. 5
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs
  10. 30
      framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs
  11. 6
      framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs
  12. 11
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs
  13. 11
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs
  14. 23
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
  15. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  16. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs
  17. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml
  18. 33
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs
  19. 65
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs
  20. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml
  21. 18
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs
  22. 40
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs
  23. 4
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs
  24. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml
  25. 18
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs
  26. 56
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs
  27. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml
  28. 27
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs
  29. 34
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs
  30. 37
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs
  31. 22
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs
  32. 19
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml
  33. 54
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs
  34. 4
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs
  35. 4
      framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs
  36. 4
      framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs
  37. 3
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  38. 1
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs

6
framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs

@ -1,6 +1,7 @@
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
@ -37,5 +38,10 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions
{
return actionDescriptor is ControllerActionDescriptor;
}
public static bool IsPageAction(this ActionDescriptor actionDescriptor)
{
return actionDescriptor is PageActionDescriptor;
}
}
}

12
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
@ -12,6 +12,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.Hosting;
using Volo.Abp.ApiVersioning;
using Volo.Abp.AspNetCore.Mvc.Conventions;
@ -20,6 +23,7 @@ using Volo.Abp.AspNetCore.Mvc.Json;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
@ -38,6 +42,9 @@ namespace Volo.Abp.AspNetCore.Mvc
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
DynamicProxyIgnoreTypes.Add<ControllerBase>();
DynamicProxyIgnoreTypes.Add<PageModel>();
context.Services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar());
}
@ -108,6 +115,9 @@ namespace Volo.Abp.AspNetCore.Mvc
//Use DI to create view components
context.Services.Replace(ServiceDescriptor.Singleton<IViewComponentActivator, ServiceBasedViewComponentActivator>());
//Use DI to create razor page
context.Services.Replace(ServiceDescriptor.Singleton<IPageModelActivatorProvider, ServiceBasedPageModelActivatorProvider>());
//Add feature providers
var partManager = context.Services.GetSingletonInstance<ApplicationPartManager>();
var application = context.Services.GetSingletonInstance<IAbpApplication>();

13
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs

@ -16,7 +16,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public static void AddAbp(this MvcOptions options, IServiceCollection services)
{
AddConventions(options, services);
AddFilters(options);
AddActionFilters(options);
AddPageFilters(options);
AddModelBinders(options);
AddMetadataProviders(options, services);
}
@ -26,7 +27,7 @@ namespace Volo.Abp.AspNetCore.Mvc
options.Conventions.Add(new AbpServiceConventionWrapper(services));
}
private static void AddFilters(MvcOptions options)
private static void AddActionFilters(MvcOptions options)
{
options.Filters.AddService(typeof(AbpAuditActionFilter));
options.Filters.AddService(typeof(AbpNoContentActionFilter));
@ -36,6 +37,14 @@ namespace Volo.Abp.AspNetCore.Mvc
options.Filters.AddService(typeof(AbpExceptionFilter));
}
private static void AddPageFilters(MvcOptions options)
{
options.Filters.AddService(typeof(AbpExceptionPageFilter));
options.Filters.AddService(typeof(AbpAuditPageFilter));
options.Filters.AddService(typeof(AbpFeaturePageFilter));
options.Filters.AddService(typeof(AbpUowPageFilter));
}
private static void AddModelBinders(MvcOptions options)
{
options.ModelBinderProviders.Insert(0, new AbpDateTimeModelBinderProvider());

103
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs

@ -0,0 +1,103 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Volo.Abp.Aspects;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
public class AbpAuditPageFilter : IAsyncPageFilter, ITransientDependency
{
protected AbpAuditingOptions Options { get; }
private readonly IAuditingHelper _auditingHelper;
private readonly IAuditingManager _auditingManager;
public AbpAuditPageFilter(IOptions<AbpAuditingOptions> options, IAuditingHelper auditingHelper, IAuditingManager auditingManager)
{
Options = options.Value;
_auditingHelper = auditingHelper;
_auditingManager = auditingManager;
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod == null || !ShouldSaveAudit(context, out var auditLog, out var auditLogAction))
{
await next();
return;
}
using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.Auditing))
{
var stopwatch = Stopwatch.StartNew();
try
{
var result = await next();
if (result.Exception != null && !result.ExceptionHandled)
{
auditLog.Exceptions.Add(result.Exception);
}
}
catch (Exception ex)
{
auditLog.Exceptions.Add(ex);
throw;
}
finally
{
stopwatch.Stop();
auditLogAction.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
auditLog.Actions.Add(auditLogAction);
}
}
}
private bool ShouldSaveAudit(PageHandlerExecutingContext context, out AuditLogInfo auditLog, out AuditLogActionInfo auditLogAction)
{
auditLog = null;
auditLogAction = null;
if (!Options.IsEnabled)
{
return false;
}
if (!context.ActionDescriptor.IsPageAction())
{
return false;
}
var auditLogScope = _auditingManager.Current;
if (auditLogScope == null)
{
return false;
}
if (!_auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, true))
{
return false;
}
auditLog = auditLogScope.Log;
auditLogAction = _auditingHelper.CreateAuditLogAction(
auditLog,
context.HandlerMethod.GetType(),
context.HandlerMethod.MethodInfo,
context.HandlerArguments
);
return true;
}
}
}

112
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs

@ -0,0 +1,112 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http;
using Volo.Abp.Json;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{
public class AbpExceptionPageFilter : IAsyncPageFilter, ITransientDependency
{
public ILogger<AbpExceptionPageFilter> Logger { get; set; }
private readonly IExceptionToErrorInfoConverter _errorInfoConverter;
private readonly IHttpExceptionStatusCodeFinder _statusCodeFinder;
private readonly IJsonSerializer _jsonSerializer;
public AbpExceptionPageFilter(
IExceptionToErrorInfoConverter errorInfoConverter,
IHttpExceptionStatusCodeFinder statusCodeFinder,
IJsonSerializer jsonSerializer)
{
_errorInfoConverter = errorInfoConverter;
_statusCodeFinder = statusCodeFinder;
_jsonSerializer = jsonSerializer;
Logger = NullLogger<AbpExceptionPageFilter>.Instance;
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod == null || !ShouldHandleException(context))
{
await next();
return;
}
var pageHandlerExecutedContext = await next();
if (pageHandlerExecutedContext.Exception == null)
{
return;;
}
await HandleAndWrapException(pageHandlerExecutedContext);
}
protected virtual bool ShouldHandleException(PageHandlerExecutingContext context)
{
//TODO: Create DontWrap attribute to control wrapping..?
if (context.ActionDescriptor.IsPageAction() &&
ActionResultHelper.IsObjectResult(context.HandlerMethod.MethodInfo.ReturnType))
{
return true;
}
if (context.HttpContext.Request.CanAccept(MimeTypes.Application.Json))
{
return true;
}
if (context.HttpContext.Request.IsAjax())
{
return true;
}
return false;
}
protected virtual async Task HandleAndWrapException(PageHandlerExecutedContext context)
{
//TODO: Trigger an AbpExceptionHandled event or something like that.
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
context.HttpContext.Response.StatusCode = (int)_statusCodeFinder.GetStatusCode(context.HttpContext, context.Exception);
var remoteServiceErrorInfo = _errorInfoConverter.Convert(context.Exception);
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
var logLevel = context.Exception.GetLogLevel();
Logger.LogWithLevel(logLevel, $"---------- {nameof(RemoteServiceErrorInfo)} ----------");
Logger.LogWithLevel(logLevel, _jsonSerializer.Serialize(remoteServiceErrorInfo, indented: true));
Logger.LogException(context.Exception, logLevel);
await context.HttpContext
.RequestServices
.GetRequiredService<IExceptionNotifier>()
.NotifyAsync(
new ExceptionNotificationContext(context.Exception)
);
context.Exception = null; //Handled!
}
}
}

44
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeaturePageFilter.cs

@ -0,0 +1,44 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
namespace Volo.Abp.AspNetCore.Mvc.Features
{
public class AbpFeaturePageFilter : IAsyncPageFilter, ITransientDependency
{
private readonly IMethodInvocationFeatureCheckerService _methodInvocationAuthorizationService;
public AbpFeaturePageFilter(IMethodInvocationFeatureCheckerService methodInvocationAuthorizationService)
{
_methodInvocationAuthorizationService = methodInvocationAuthorizationService;
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod == null || !context.ActionDescriptor.IsPageAction())
{
await next();
return;
}
var methodInfo = context.HandlerMethod.MethodInfo;
using (AbpCrossCuttingConcerns.Applying(context.HandlerInstance, AbpCrossCuttingConcerns.FeatureChecking))
{
await _methodInvocationAuthorizationService.CheckAsync(
new MethodInvocationFeatureCheckerContext(methodInfo)
);
await next();
}
}
}
}

105
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -0,0 +1,105 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace Volo.Abp.AspNetCore.Mvc.Uow
{
public class AbpUowPageFilter : IAsyncPageFilter, ITransientDependency
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly AbpUnitOfWorkDefaultOptions _defaultOptions;
public AbpUowPageFilter(IUnitOfWorkManager unitOfWorkManager, IOptions<AbpUnitOfWorkDefaultOptions> options)
{
_unitOfWorkManager = unitOfWorkManager;
_defaultOptions = options.Value;
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod == null || !context.ActionDescriptor.IsPageAction())
{
await next();
return;
}
var methodInfo = context.HandlerMethod.MethodInfo;
var unitOfWorkAttr = UnitOfWorkHelper.GetUnitOfWorkAttributeOrNull(methodInfo);
context.HttpContext.Items["_AbpActionInfo"] = new AbpActionInfoInHttpContext
{
IsObjectResult = ActionResultHelper.IsObjectResult(context.HandlerMethod.MethodInfo.ReturnType)
};
if (unitOfWorkAttr?.IsDisabled == true)
{
await next();
return;
}
var options = CreateOptions(context, unitOfWorkAttr);
//Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware
if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options))
{
var result = await next();
if (!Succeed(result))
{
await RollbackAsync(context);
}
return;
}
//Begin a new, independent unit of work
using (var uow = _unitOfWorkManager.Begin(options))
{
var result = await next();
if (Succeed(result))
{
await uow.CompleteAsync(context.HttpContext.RequestAborted);
}
}
}
private AbpUnitOfWorkOptions CreateOptions(PageHandlerExecutingContext context, UnitOfWorkAttribute unitOfWorkAttribute)
{
var options = new AbpUnitOfWorkOptions();
unitOfWorkAttribute?.SetOptions(options);
if (unitOfWorkAttribute?.IsTransactional == null)
{
options.IsTransactional = _defaultOptions.CalculateIsTransactional(
autoValue: !string.Equals(context.HttpContext.Request.Method, HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase)
);
}
return options;
}
private async Task RollbackAsync(PageHandlerExecutingContext context)
{
var currentUow = _unitOfWorkManager.Current;
if (currentUow != null)
{
await currentUow.RollbackAsync(context.HttpContext.RequestAborted);
}
}
private static bool Succeed(PageHandlerExecutedContext result)
{
return result.Exception == null || result.ExceptionHandled;
}
}
}

6
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs

@ -1,6 +1,7 @@
using System;
using System.Linq;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Auditing
{
@ -16,6 +17,11 @@ namespace Volo.Abp.Auditing
private static bool ShouldIntercept(Type type)
{
if (DynamicProxyIgnoreTypes.Contains(type))
{
return false;
}
if (ShouldAuditTypeByDefault(type))
{
return true;

5
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AuthorizationInterceptorRegistrar.cs

@ -3,6 +3,7 @@ using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Authorization
{
@ -18,8 +19,8 @@ namespace Volo.Abp.Authorization
private static bool ShouldIntercept(Type type)
{
return type.IsDefined(typeof(AuthorizeAttribute), true) ||
AnyMethodHasAuthorizeAttribute(type);
return !DynamicProxyIgnoreTypes.Contains(type) &&
(type.IsDefined(typeof(AuthorizeAttribute), true) || AnyMethodHasAuthorizeAttribute(type));
}
private static bool AnyMethodHasAuthorizeAttribute(Type implementationType)

30
framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Threading;
namespace Volo.Abp.DynamicProxy
{
/// <summary>
/// Castle's dynamic proxy class feature will have performance issues for some components, such as the controller of Asp net core MVC.
/// For related discussions, see: https://github.com/castleproject/Core/issues/486 https://github.com/abpframework/abp/issues/3180
/// The Abp framework may enable interceptors for certain components (UOW, Auditing, Authorization, etc.), which requires dynamic proxy classes, but will cause application performance to decline.
/// We need to use other methods for the controller to implement interception, such as middleware or MVC / Page filters.
/// So we provide some ignored types to avoid enabling dynamic proxy classes.
/// By default it is empty. When you use middleware or filters for these components in your application, you can add these types to the list.
/// </summary>
public static class DynamicProxyIgnoreTypes
{
private static HashSet<Type> IgnoredTypes { get; } = new HashSet<Type>();
public static void Add<T>()
{
IgnoredTypes.Locking(() => IgnoredTypes.AddIfNotContains(typeof(T)));
}
public static bool Contains(Type type, bool includeDerivedTypes = true)
{
return includeDerivedTypes ? IgnoredTypes.Any(t => t.IsAssignableFrom(type)) : IgnoredTypes.Contains(type);
}
}
}

6
framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureInterceptorRegistrar.cs

@ -2,6 +2,7 @@
using System.Linq;
using System.Reflection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Features
{
@ -17,8 +18,9 @@ namespace Volo.Abp.Features
private static bool ShouldIntercept(Type type)
{
return type.IsDefined(typeof(RequiresFeatureAttribute), true) ||
AnyMethodHasRequiresFeatureAttribute(type);
return !DynamicProxyIgnoreTypes.Contains(type) &&
(type.IsDefined(typeof(RequiresFeatureAttribute), true) ||
AnyMethodHasRequiresFeatureAttribute(type));
}
private static bool AnyMethodHasRequiresFeatureAttribute(Type implementationType)

11
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptorRegistrar.cs

@ -1,5 +1,7 @@
using System.Reflection;
using System;
using System.Reflection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Uow
{
@ -7,10 +9,15 @@ namespace Volo.Abp.Uow
{
public static void RegisterIfNeeded(IOnServiceRegistredContext context)
{
if (UnitOfWorkHelper.IsUnitOfWorkType(context.ImplementationType.GetTypeInfo()))
if (ShouldIntercept(context.ImplementationType))
{
context.Interceptors.TryAdd<UnitOfWorkInterceptor>();
}
}
private static bool ShouldIntercept(Type type)
{
return !DynamicProxyIgnoreTypes.Contains(type) && UnitOfWorkHelper.IsUnitOfWorkType(type.GetTypeInfo());
}
}
}

11
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptorRegistrar.cs

@ -1,4 +1,6 @@
using Volo.Abp.DependencyInjection;
using System;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Validation
{
@ -6,10 +8,15 @@ namespace Volo.Abp.Validation
{
public static void RegisterIfNeeded(IOnServiceRegistredContext context)
{
if (typeof(IValidationEnabled).IsAssignableFrom(context.ImplementationType))
if (ShouldIntercept(context.ImplementationType))
{
context.Interceptors.TryAdd<ValidationInterceptor>();
}
}
private static bool ShouldIntercept(Type type)
{
return !DynamicProxyIgnoreTypes.Contains(type) && typeof(IValidationEnabled).IsAssignableFrom(type);
}
}
}

23
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj

@ -24,6 +24,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.AspNetCore.Mvc.UI\Volo.Abp.AspNetCore.Mvc.UI.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Tests\Volo.Abp.AspNetCore.Tests.csproj" />
@ -39,6 +40,28 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Content Update="Volo\Abp\AspNetCore\Mvc\Uow\UnitOfWorkTestPage.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Volo\Abp\AspNetCore\Mvc\Auditing\AuditTestPage.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Volo\Abp\AspNetCore\Mvc\Features\FeatureTestPage.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Volo\Abp\AspNetCore\Mvc\ExceptionHandling\ExceptionTestPage.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Volo\Abp\AspNetCore\Mvc\Authorization\AuthTestPage.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<!-- https://github.com/NuGet/Home/issues/4412. -->
<Target Name="CopyDepsFiles" AfterTargets="Build" Condition="'$(TargetFramework)'!=''">

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -1,6 +1,9 @@
using System;
using System;
using System.Linq;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Authorization;
using Volo.Abp.AspNetCore.Mvc.Localization;
@ -73,6 +76,11 @@ namespace Volo.Abp.AspNetCore.Mvc
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
});
Configure<RazorPagesOptions>(options =>
{
options.RootDirectory = "/Volo/Abp/AspNetCore/Mvc";
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs

@ -51,6 +51,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object()
{

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml

@ -0,0 +1,19 @@
@page
@model Volo.Abp.AspNetCore.Mvc.Auditing.AuditTestPage
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>

33
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage.cshtml.cs

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Auditing;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
public class AuditTestPage : AbpPageModel
{
private readonly AbpAuditingOptions _options;
public AuditTestPage(IOptions<AbpAuditingOptions> options)
{
_options = options.Value;
}
public IActionResult OnGetAuditSuccessForGetRequests()
{
return new OkResult();
}
public IActionResult OnGetAuditFailForGetRequests()
{
throw new UserFriendlyException("Exception occurred!");
}
public ObjectResult OnGetAuditFailForGetRequestsReturningObject()
{
throw new UserFriendlyException("Exception occurred!");
}
}
}

65
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestPage_Tests.cs

@ -0,0 +1,65 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using NSubstitute;
using Volo.Abp.Auditing;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
public class AuditTestPage_Tests : AspNetCoreMvcTestBase
{
private readonly AbpAuditingOptions _options;
private IAuditingStore _auditingStore;
public AuditTestPage_Tests()
{
_options = ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
_auditingStore = ServiceProvider.GetRequiredService<IAuditingStore>();
}
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
_auditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(_auditingStore));
base.ConfigureServices(context, services);
}
[Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Success_For_GetRequests()
{
_options.IsEnabledForGetRequests = true;
_options.AlwaysLogOnException = false;
await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditSuccessForGetRequests");
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Exception_Always()
{
_options.IsEnabled = true;
_options.AlwaysLogOnException = true;
try
{
await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditFailForGetRequests", System.Net.HttpStatusCode.Forbidden);
}
catch { }
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object()
{
_options.IsEnabled = true;
_options.AlwaysLogOnException = true;
await GetResponseAsync("/Auditing/AuditTestPage?handler=AuditFailForGetRequestsReturningObject", System.Net.HttpStatusCode.Forbidden);
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml

@ -0,0 +1,19 @@
@page
@model Volo.Abp.AspNetCore.Mvc.Authorization.AuthTestPage
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>

18
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage.cshtml.cs

@ -0,0 +1,18 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.Abp.AspNetCore.Mvc.Authorization
{
[Authorize]
public class AuthTestPage : AbpPageModel
{
public static Guid FakeUserId { get; } = Guid.NewGuid();
public ActionResult OnGet()
{
return Content("OK");
}
}
}

40
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestPage_Tests.cs

@ -0,0 +1,40 @@
using System.Security.Claims;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Autofac;
using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Authorization
{
[DependsOn(
typeof(AbpAspNetCoreTestBaseModule),
typeof(AbpMemoryDbTestModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpAutofacModule)
)]
public class AuthTestPage_Tests: AspNetCoreMvcTestBase
{
private readonly FakeUserClaims _fakeRequiredService;
public AuthTestPage_Tests()
{
_fakeRequiredService = GetRequiredService<FakeUserClaims>();
}
[Fact]
public async Task Should_Call_Simple_Authorized_Method_With_Authenticated_User()
{
_fakeRequiredService.Claims.AddRange(new[]
{
new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString())
});
var result = await GetResponseAsStringAsync("/Authorization/AuthTestPage");
result.ShouldBe("OK");
}
}
}

4
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs

@ -30,9 +30,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe("This is a sample exception!");
#pragma warning disable 4014
_fakeExceptionSubscriber
.Received()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
[Fact]
@ -44,9 +46,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
)
);
#pragma warning disable 4014
_fakeExceptionSubscriber
.DidNotReceive()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml

@ -0,0 +1,19 @@
@page
@model Volo.Abp.AspNetCore.Mvc.ExceptionHandling.ExceptionTestPage
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>

18
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{
public class ExceptionTestPage : AbpPageModel
{
public void OnGetUserFriendlyException1()
{
throw new UserFriendlyException("This is a sample exception!");
}
public IActionResult OnGetUserFriendlyException2()
{
throw new UserFriendlyException("This is a sample exception!");
}
}
}

56
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs

@ -0,0 +1,56 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NSubstitute;
using Shouldly;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{
public class ExceptionTestPage_Tests : AspNetCoreMvcTestBase
{
private IExceptionSubscriber _fakeExceptionSubscriber;
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
base.ConfigureServices(context, services);
_fakeExceptionSubscriber = Substitute.For<IExceptionSubscriber>();
services.AddSingleton(_fakeExceptionSubscriber);
}
[Fact]
public async Task Should_Return_RemoteServiceErrorResponse_For_UserFriendlyException_For_Void_Return_Value()
{
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/ExceptionHandling/ExceptionTestPage?handler=UserFriendlyException1", HttpStatusCode.Forbidden);
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe("This is a sample exception!");
#pragma warning disable 4014
_fakeExceptionSubscriber
.Received()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
[Fact]
public async Task Should_Not_Handle_Exceptions_For_ActionResult_Return_Values()
{
await Assert.ThrowsAsync<UserFriendlyException>(
async () => await GetResponseAsObjectAsync<RemoteServiceErrorResponse>(
"/ExceptionHandling/ExceptionTestPage?handler=UserFriendlyException2"
)
);
#pragma warning disable 4014
_fakeExceptionSubscriber
.DidNotReceive()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml

@ -0,0 +1,19 @@
@page
@model Volo.Abp.AspNetCore.Mvc.Features.FeatureTestPage
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>

27
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage.cshtml.cs

@ -0,0 +1,27 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Features;
namespace Volo.Abp.AspNetCore.Mvc.Features
{
public class FeatureTestPage : AbpPageModel
{
[RequiresFeature("AllowedFeature")]
public Task OnGetAllowedFeatureAsync()
{
return Task.CompletedTask;
}
[RequiresFeature("NotAllowedFeature")]
public void OnGetNotAllowedFeature()
{
}
public ObjectResult OnGetNoFeature()
{
return new ObjectResult(42);
}
}
}

34
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Features/FeatureTestPage_Tests.cs

@ -0,0 +1,34 @@
using System.Net;
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Features
{
public class FeatureTestPage_Tests : AspNetCoreMvcTestBase
{
[Fact]
public async Task Should_Allow_Enabled_Features()
{
await GetResponseAsStringAsync(
"/Features/FeatureTestPage?handler=AllowedFeature"
);
}
[Fact]
public async Task Should_Not_Allow_Not_Enabled_Features()
{
await GetResponseAsStringAsync(
"/Features/FeatureTestPage?handler=NotAllowedFeature",
HttpStatusCode.Unauthorized
);
}
[Fact]
public async Task Should_Allow_Actions_With_No_Feature()
{
await GetResponseAsStringAsync(
"/Features/FeatureTestPage?handler=NoFeature"
);
}
}
}

37
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs

@ -0,0 +1,37 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Http;
using Volo.Abp.Json;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Uow
{
public class UnitOfWorkPageFilter_Exception_Rollback_Tests : AspNetCoreMvcTestBase
{
[Fact]
public async Task Should_Rollback_Transaction_For_Handled_Exceptions()
{
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/Uow/UnitOfWorkTestPage?handler=HandledException", HttpStatusCode.Forbidden);
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe("This is a sample exception!");
}
[Fact]
public async Task Should_Gracefully_Handle_Exceptions_On_Complete()
{
var response = await GetResponseAsync("/Uow/UnitOfWorkTestPage?handler=ExceptionOnComplete", HttpStatusCode.Forbidden);
response.Headers.GetValues(AbpHttpConsts.AbpErrorFormat).FirstOrDefault().ShouldBe("true");
var resultAsString = await response.Content.ReadAsStringAsync();
var result = ServiceProvider.GetRequiredService<IJsonSerializer>().Deserialize<RemoteServiceErrorResponse>(resultAsString);
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe(TestUnitOfWorkConfig.ExceptionOnCompleteMessage);
}
}
}

22
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Tests.cs

@ -0,0 +1,22 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Uow
{
public class UnitOfWorkPageFilter_Tests: AspNetCoreMvcTestBase
{
[Fact]
public async Task Get_Actions_Should_Not_Be_Transactional()
{
await GetResponseAsStringAsync("/Uow/UnitOfWorkTestPage?handler=RequiresUow");
}
[Fact]
public async Task Non_Get_Actions_Should_Be_Transactional()
{
var result = await Client.PostAsync("/Uow/UnitOfWorkTestPage?handler=RequiresUow", null);
result.IsSuccessStatusCode.ShouldBeTrue();
}
}
}

19
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml

@ -0,0 +1,19 @@
@page
@model Volo.Abp.AspNetCore.Mvc.Uow.UnitOfWorkTestPage
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>

54
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestPage.cshtml.cs

@ -0,0 +1,54 @@
using Microsoft.AspNetCore.Mvc;
using Shouldly;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Uow;
namespace Volo.Abp.AspNetCore.Mvc.Uow
{
[IgnoreAntiforgeryToken]
public class UnitOfWorkTestPage : AbpPageModel
{
private readonly TestUnitOfWorkConfig _testUnitOfWorkConfig;
public UnitOfWorkTestPage(TestUnitOfWorkConfig testUnitOfWorkConfig)
{
_testUnitOfWorkConfig = testUnitOfWorkConfig;
}
public IActionResult OnGetRequiresUow()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse();
return Content("OK");
}
public IActionResult OnPostRequiresUow()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeTrue();
return Content("OK");
}
[UnitOfWork(isTransactional: true)]
public void OnGetHandledException()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeTrue();
throw new UserFriendlyException("This is a sample exception!");
}
public ObjectResult OnGetExceptionOnComplete()
{
CurrentUnitOfWork.ShouldNotBeNull();
CurrentUnitOfWork.Options.IsTransactional.ShouldBeFalse();
_testUnitOfWorkConfig.ThrowExceptionOnComplete = true;
//Prevent rendering of pages.
return new ObjectResult("");
}
}
}

4
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.TestServices;
using Volo.Abp.Autofac;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Modularity;
namespace Volo.Abp.Authorization
@ -13,7 +14,8 @@ namespace Volo.Abp.Authorization
{
context.Services.OnRegistred(onServiceRegistredContext =>
{
if (typeof(IMyAuthorizedService1).IsAssignableFrom(onServiceRegistredContext.ImplementationType))
if (typeof(IMyAuthorizedService1).IsAssignableFrom(onServiceRegistredContext.ImplementationType) &&
!DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType))
{
onServiceRegistredContext.Interceptors.TryAdd<AuthorizationInterceptor>();
}

4
framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Autofac;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Modularity;
using Volo.Abp.Testing;
using Volo.Abp.Validation;
@ -108,7 +109,8 @@ namespace Volo.Abp.FluentValidation
{
context.Services.OnRegistred(onServiceRegistredContext =>
{
if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType))
if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType) &&
!DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType))
{
onServiceRegistredContext.Interceptors.TryAdd<ValidationInterceptor>();
}

4
framework/test/Volo.Abp.Validation.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs

@ -8,6 +8,7 @@ using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Autofac;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Modularity;
using Volo.Abp.Testing;
using Xunit;
@ -198,7 +199,8 @@ namespace Volo.Abp.Validation
{
context.Services.OnRegistred(onServiceRegistredContext =>
{
if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType))
if (typeof(IMyAppService).IsAssignableFrom(onServiceRegistredContext.ImplementationType) &&
!DynamicProxyIgnoreTypes.Contains(onServiceRegistredContext.ImplementationType))
{
onServiceRegistredContext.Interceptors.TryAdd<ValidationInterceptor>();
}

3
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs

@ -76,7 +76,6 @@ namespace Volo.Abp.Account.Web.Pages.Account
return Page();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnPostAsync(string action)
{
await CheckLocalLoginAsync();
@ -147,7 +146,6 @@ namespace Volo.Abp.Account.Web.Pages.Account
.ToList();
}
[UnitOfWork]
public virtual async Task<IActionResult> OnPostExternalLogin(string provider)
{
var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash });
@ -157,7 +155,6 @@ namespace Volo.Abp.Account.Web.Pages.Account
return await Task.FromResult(Challenge(properties, provider));
}
[UnitOfWork]
public virtual async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
{
//TODO: Did not implemented Identity Server 4 sample for this method (see ExternalLoginCallback in Quickstart of IDS4 sample)

1
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs

@ -36,7 +36,6 @@ namespace Volo.Abp.Account.Web.Pages.Account
await CheckSelfRegistrationAsync();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();

Loading…
Cancel
Save