Skip to content

Commit

Permalink
Resolved #2514: Remove Async suffix for dynamic async controller acti…
Browse files Browse the repository at this point in the history
…ons (both for web api and asp.net core mvc)
  • Loading branch information
hikalkan committed Nov 15, 2017
1 parent 652208b commit c9b6368
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
using Abp.Dependency;
using Abp.Extensions;
using Abp.Reflection.Extensions;
using Abp.Threading;
using Abp.Web.Api.Modeling;
using Abp.Web.Api.ProxyScripting.Configuration;
using Castle.Core.Logging;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
Expand All @@ -20,13 +22,16 @@ public class AspNetCoreApiDescriptionModelProvider : IApiDescriptionModelProvide

private readonly IApiDescriptionGroupCollectionProvider _descriptionProvider;
private readonly AbpAspNetCoreConfiguration _configuration;
private readonly IApiProxyScriptingConfiguration _apiProxyScriptingConfiguration;

public AspNetCoreApiDescriptionModelProvider(
IApiDescriptionGroupCollectionProvider descriptionProvider,
AbpAspNetCoreConfiguration configuration)
AbpAspNetCoreConfiguration configuration,
IApiProxyScriptingConfiguration apiProxyScriptingConfiguration)
{
_descriptionProvider = descriptionProvider;
_configuration = configuration;
_apiProxyScriptingConfiguration = apiProxyScriptingConfiguration;

Logger = NullLogger.Instance;
}
Expand Down Expand Up @@ -57,17 +62,18 @@ private void AddApiDescriptionToModel(ApiDescription apiDescription, Application
var controllerModel = moduleModel.GetOrAddController(GetControllerName(apiDescription));

var method = apiDescription.ActionDescriptor.GetMethodInfo();
var methodName = GetNormalizedMethodName(controllerModel, method);

if (controllerModel.Actions.ContainsKey(method.Name))
if (controllerModel.Actions.ContainsKey(methodName))
{
Logger.Warn($"Controller '{controllerModel.Name}' contains more than one action with name '{method.Name}' for module '{moduleModel.Name}'. Ignored: " + apiDescription.ActionDescriptor.GetMethodInfo());
Logger.Warn($"Controller '{controllerModel.Name}' contains more than one action with name '{methodName}' for module '{moduleModel.Name}'. Ignored: " + apiDescription.ActionDescriptor.GetMethodInfo());
return;
}

var returnValue = new ReturnValueApiDescriptionModel(method.ReturnType);

var actionModel = controllerModel.AddAction(new ActionApiDescriptionModel(
method.Name,
methodName,
returnValue,
apiDescription.RelativePath,
apiDescription.HttpMethod
Expand All @@ -76,6 +82,27 @@ private void AddApiDescriptionToModel(ApiDescription apiDescription, Application
AddParameterDescriptionsToModel(actionModel, method, apiDescription);
}

private string GetNormalizedMethodName(ControllerApiDescriptionModel controllerModel, MethodInfo method)
{
if (!_apiProxyScriptingConfiguration.RemoveAsyncPostfixOnProxyGeneration)
{
return method.Name;
}

if (!method.IsAsync())
{
return method.Name;
}

var normalizedName = method.Name.RemovePostFix("Async");
if (controllerModel.Actions.ContainsKey(normalizedName))
{
return method.Name;
}

return normalizedName;
}

private static string GetControllerName(ApiDescription apiDescription)
{
return apiDescription.GroupName?.RemovePostFix(ApplicationService.CommonPostfixes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
using System.Linq;
using Abp.Reflection;
using System.Web.Http;
using Abp.Dependency;
using Abp.Extensions;
using Abp.Threading;
using Abp.Web.Api.ProxyScripting.Configuration;

namespace Abp.WebApi.Controllers.Dynamic.Builders
{
Expand Down Expand Up @@ -50,18 +54,40 @@ public IApiControllerBuilder Controller
{
get { return _controller; }
}

private readonly ApiControllerBuilder<T> _controller;
private readonly IIocResolver _iocResolver;

/// <summary>
/// Creates a new <see cref="ApiControllerActionBuilder{T}"/> object.
/// </summary>
/// <param name="apiControllerBuilder">Reference to the <see cref="ApiControllerBuilder{T}"/> which created this object</param>
/// <param name="methodInfo">Method</param>
public ApiControllerActionBuilder(ApiControllerBuilder<T> apiControllerBuilder, MethodInfo methodInfo)
/// <param name="iocResolver"></param>
public ApiControllerActionBuilder(ApiControllerBuilder<T> apiControllerBuilder, MethodInfo methodInfo, IIocResolver iocResolver)
{
_controller = apiControllerBuilder;
_iocResolver = iocResolver;
Method = methodInfo;
ActionName = Method.Name;
ActionName = GetNormalizedActionName();
}

private string GetNormalizedActionName()
{
using (var config = _iocResolver.ResolveAsDisposable<IApiProxyScriptingConfiguration>())
{
if (!config.Object.RemoveAsyncPostfixOnProxyGeneration)
{
return Method.Name;
}
}

if (!Method.IsAsync())
{
return Method.Name;
}

return Method.Name.RemovePostFix("Async");
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public ApiControllerBuilder(string serviceName, IIocResolver iocResolver)

foreach (var methodInfo in DynamicApiControllerActionHelper.GetMethodsOfType(typeof(T)))
{
var actionBuilder = new ApiControllerActionBuilder<T>(this, methodInfo);
var actionBuilder = new ApiControllerActionBuilder<T>(this, methodInfo, iocResolver);

var remoteServiceAttr = methodInfo.GetSingleAttributeOrNull<RemoteServiceAttribute>();
if (remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(methodInfo))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ public class ApiProxyScriptingConfiguration : IApiProxyScriptingConfiguration
{
public IDictionary<string, Type> Generators { get; }

public bool RemoveAsyncPostfixOnProxyGeneration { get; set; }

public ApiProxyScriptingConfiguration()
{
Generators = new Dictionary<string, Type>();
RemoveAsyncPostfixOnProxyGeneration = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,10 @@ public interface IApiProxyScriptingConfiguration
/// Used to add/replace proxy script generators.
/// </summary>
IDictionary<string, Type> Generators { get; }

/// <summary>
/// Default: true.
/// </summary>
bool RemoveAsyncPostfixOnProxyGeneration { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Abp/Auditing/AuditingInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void Intercept(IInvocation invocation)

var auditInfo = _auditingHelper.CreateAuditInfo(invocation.TargetType, invocation.MethodInvocationTarget, invocation.Arguments);

if (AsyncHelper.IsAsyncMethod(invocation.Method))
if (invocation.Method.IsAsync())
{
PerformAsyncAuditing(invocation, auditInfo);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Abp/Domain/Uow/UnitOfWorkInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void Intercept(IInvocation invocation)

private void PerformUow(IInvocation invocation, UnitOfWorkOptions options)
{
if (AsyncHelper.IsAsyncMethod(invocation.Method))
if (invocation.Method.IsAsync())
{
PerformAsyncUow(invocation, options);
}
Expand Down
14 changes: 12 additions & 2 deletions src/Abp/Threading/AsyncHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,22 @@ public static class AsyncHelper
/// Checks if given method is an async method.
/// </summary>
/// <param name="method">A method to check</param>
public static bool IsAsyncMethod(MethodInfo method)
public static bool IsAsync(this MethodInfo method)
{
return (
method.ReturnType == typeof(Task) ||
(method.ReturnType.GetTypeInfo().IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
);
);
}

/// <summary>
/// Checks if given method is an async method.
/// </summary>
/// <param name="method">A method to check</param>
[Obsolete("Use MethodInfo.IsAsync() extension method!")]
public static bool IsAsyncMethod(MethodInfo method)
{
return method.IsAsync();
}

/// <summary>
Expand Down
8 changes: 4 additions & 4 deletions test/Abp.Tests/Threading/InternalAsyncHelper_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public class InternalAsyncHelper_Tests
[Fact]
public void IsAsync_Should_Work()
{
AsyncHelper.IsAsyncMethod(GetType().GetMethod("MyMethod1Sync", BindingFlags.NonPublic | BindingFlags.Instance)).ShouldBe(false);
AsyncHelper.IsAsyncMethod(GetType().GetMethod("MyMethod1Async", BindingFlags.NonPublic | BindingFlags.Instance)).ShouldBe(true);
AsyncHelper.IsAsyncMethod(GetType().GetMethod("MyMethod2Sync", BindingFlags.NonPublic | BindingFlags.Instance)).ShouldBe(false);
AsyncHelper.IsAsyncMethod(GetType().GetMethod("MyMethod2Async", BindingFlags.NonPublic | BindingFlags.Instance)).ShouldBe(true);
GetType().GetMethod("MyMethod1Sync", BindingFlags.NonPublic | BindingFlags.Instance).IsAsync().ShouldBe(false);
GetType().GetMethod("MyMethod1Async", BindingFlags.NonPublic | BindingFlags.Instance).IsAsync().ShouldBe(true);
GetType().GetMethod("MyMethod2Sync", BindingFlags.NonPublic | BindingFlags.Instance).IsAsync().ShouldBe(false);
GetType().GetMethod("MyMethod2Async", BindingFlags.NonPublic | BindingFlags.Instance).IsAsync().ShouldBe(true);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Abp.Application.Services;
using AbpAspNetCoreDemo.Core.Application.Dtos;
using AbpAspNetCoreDemo.Core.Domain;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.UI;
Expand All @@ -22,9 +21,9 @@ public ProductAppService(IRepository<Product> productRepository)
_productRepository = productRepository;
}

public List<ProductDto> GetAll()
public async Task<List<ProductDto>> GetAllAsync()
{
return ObjectMapper.Map<List<ProductDto>>(_productRepository.GetAll().ToList());
return ObjectMapper.Map<List<ProductDto>>(await _productRepository.GetAllListAsync());
}

public int CreateProduct(ProductCreateInput input)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" />
</ItemGroup>

<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
</ItemGroup>

<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
Expand Down
2 changes: 1 addition & 1 deletion test/aspnet-core-demo/AbpAspNetCoreDemo/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
{
options.PlugInSources.Add(
new AssemblyFileListPlugInSource(
Path.Combine(_env.ContentRootPath, @"..\AbpAspNetCoreDemo.PlugIn\bin\Debug\net461\AbpAspNetCoreDemo.PlugIn.dll")
Path.Combine(_env.ContentRootPath, @"..\AbpAspNetCoreDemo.PlugIn\bin\Debug\netstandard2.0\AbpAspNetCoreDemo.PlugIn.dll")
)
);
Expand Down

0 comments on commit c9b6368

Please sign in to comment.