diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceControllerFeatureProvider.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceControllerFeatureProvider.cs
new file mode 100644
index 0000000000..1ef53867b6
--- /dev/null
+++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceControllerFeatureProvider.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.Application.Services;
+using Volo.Abp.Http;
+using Volo.Abp.Reflection;
+
+namespace Volo.Abp.AspNetCore.Mvc
+{
+ ///
+ /// Used to add application services as controller.
+ ///
+ public class AbpAppServiceControllerFeatureProvider : ControllerFeatureProvider
+ {
+ private readonly IAbpApplication _application;
+
+ public AbpAppServiceControllerFeatureProvider(IAbpApplication application)
+ {
+ _application = application;
+ }
+
+ protected override bool IsController(TypeInfo typeInfo)
+ {
+ var type = typeInfo.AsType();
+
+ if (!typeof(IApplicationService).IsAssignableFrom(type) ||
+ !typeInfo.IsPublic || typeInfo.IsAbstract || typeInfo.IsGenericType)
+ {
+ return false;
+ }
+
+ var remoteServiceAttr = ReflectionHelper.GetSingleAttributeOrDefault(typeInfo);
+
+ if (remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(type))
+ {
+ return false;
+ }
+
+ var configuration = _application.ServiceProvider.GetRequiredService>().Value.ControllerAssemblySettings.GetSettingOrNull(type);
+ return configuration != null && configuration.TypePredicate(type);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
index 3f0ce600da..dd5c302b5d 100644
--- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
+++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
@@ -1,6 +1,8 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.DependencyInjection;
@@ -9,6 +11,10 @@ using Volo.Abp.AspNetCore.EmbeddedFiles;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Infrastructure;
+using Microsoft.AspNetCore.Mvc.ViewComponents;
+using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Volo.Abp.AspNetCore.Mvc
{
@@ -35,6 +41,26 @@ namespace Volo.Abp.AspNetCore.Mvc
)
)
);
+ }
+
+ public override void PostConfigureServices(IServiceCollection services)
+ {
+ //TODO: Consider to use services.AddMvc() and move this to ConfigureServices method!
+
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+
+ //Use DI to create controllers
+ services.Replace(ServiceDescriptor.Transient());
+
+ //Use DI to create view components
+ services.Replace(ServiceDescriptor.Singleton());
+
+ //Add feature providers
+ var partManager = services.GetSingletonInstance();
+ var application = services.GetSingletonInstance();
+
+ partManager.FeatureProviders.Add(new AbpAppServiceControllerFeatureProvider(application));
services.Configure(mvcOptions =>
{
@@ -55,11 +81,40 @@ namespace Volo.Abp.AspNetCore.Mvc
return;
}
- var moduleContainer = context.ServiceProvider.GetRequiredService();
+ //Plugin modules
+ var moduleAssemblies = context
+ .ServiceProvider
+ .GetRequiredService()
+ .Modules
+ .Where(m => m.IsLoadedAsPlugIn)
+ .Select(m => m.Type.Assembly)
+ .Distinct();
- foreach (var module in moduleContainer.Modules.Where(m => m.IsLoadedAsPlugIn))
+ AddToApplicationParts(partManager, moduleAssemblies);
+
+ //Controllers for application services
+ var controllerAssemblies = context
+ .ServiceProvider
+ .GetRequiredService>()
+ .Value
+ .ControllerAssemblySettings
+ .Select(s => s.Assembly)
+ .Distinct();
+
+ AddToApplicationParts(partManager, controllerAssemblies);
+ }
+
+ private static void AddToApplicationParts(ApplicationPartManager partManager, IEnumerable moduleAssemblies)
+ {
+ foreach (var moduleAssembly in moduleAssemblies)
{
- partManager.ApplicationParts.Add(new AssemblyPart(module.Type.GetTypeInfo().Assembly));
+ if (partManager.ApplicationParts.OfType().Any(p => p.Assembly == moduleAssembly))
+ {
+ continue;
+ }
+
+
+ partManager.ApplicationParts.Add(new AssemblyPart(moduleAssembly));
}
}
}
diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs
index d302985911..0b962f8f13 100644
--- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs
+++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs
@@ -13,6 +13,7 @@ namespace Volo.Abp.AspNetCore.Mvc
public AbpAspNetCoreMvcOptions()
{
+ ControllerAssemblySettings = new ControllerAssemblySettingList();
FormBodyBindingIgnoredTypes = new List
{
typeof(IFormFile)
diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs
index a18e8a6848..6656baaa5b 100644
--- a/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs
+++ b/src/Volo.Abp/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs
@@ -25,9 +25,12 @@ namespace Volo.Abp
ServiceProvider = serviceProvider;
- ServiceProvider
- .GetRequiredService()
- .InitializeModules(new ApplicationInitializationContext(ServiceProvider));
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ ServiceProvider
+ .GetRequiredService()
+ .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider));
+ }
}
}
}
diff --git a/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs b/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs
index c46c4a8373..82c1718dd7 100644
--- a/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs
+++ b/src/Volo.Abp/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs
@@ -36,9 +36,13 @@ namespace Volo.Abp
{
ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope();
ServiceProvider = ServiceScope.ServiceProvider;
- ServiceProvider
- .GetRequiredService()
- .InitializeModules(new ApplicationInitializationContext(ServiceProvider));
+
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ ServiceProvider
+ .GetRequiredService()
+ .InitializeModules(new ApplicationInitializationContext(scope.ServiceProvider));
+ }
}
public override void Dispose()
diff --git a/src/Volo.Abp/Volo/Abp/Application/Services/CrudAppServiceBase.cs b/src/Volo.Abp/Volo/Abp/Application/Services/CrudAppServiceBase.cs
index 24f89410ba..a8c0671a69 100644
--- a/src/Volo.Abp/Volo/Abp/Application/Services/CrudAppServiceBase.cs
+++ b/src/Volo.Abp/Volo/Abp/Application/Services/CrudAppServiceBase.cs
@@ -4,6 +4,7 @@ using System.Linq.Dynamic.Core;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
+using Volo.Abp.ObjectMapping;
namespace Volo.Abp.Application.Services
{
diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
index 264a146eb0..8e0059cd4a 100644
--- a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
+++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
@@ -19,6 +19,7 @@
+
diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
index e249dae4b2..e712b05b18 100644
--- a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
+++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/AppModule.cs
@@ -1,19 +1,31 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Modularity;
+using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.TestBase;
+using Volo.Abp.Autofac;
+using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
+using Volo.Abp.TestApp;
namespace Volo.Abp.AspNetCore.App
{
[DependsOn(
- typeof(AbpAspNetCoreTestBaseModule)
+ typeof(AbpAspNetCoreTestBaseModule),
+ typeof(AbpMemoryDbTestModule),
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(AbpAutofacModule)
)]
public class AppModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
+
+ services.Configure(options =>
+ {
+ options.CreateControllersForAppServices(typeof(TestAppModule).Assembly);
+ });
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/Startup.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/Startup.cs
index 565b801b15..8e09c6ba0f 100644
--- a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/Startup.cs
+++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/Startup.cs
@@ -17,7 +17,6 @@ namespace Volo.Abp.AspNetCore.App
//TODO: This is needed because ASP.NET Core does not use IServiceProviderFactory!
return services.BuildServiceProviderFromFactory();
- //return services.BuildServiceProvider();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AspNetCoreMultiTenancyTestBase.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AspNetCoreMvcTestBase.cs
similarity index 100%
rename from test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AspNetCoreMultiTenancyTestBase.cs
rename to test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AspNetCoreMvcTestBase.cs
diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs
new file mode 100644
index 0000000000..0d7d91999f
--- /dev/null
+++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PersonAppService_Tests.cs
@@ -0,0 +1,18 @@
+using Shouldly;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.TestApp.Application;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.Mvc
+{
+ public class PersonAppService_Tests : AspNetCoreMvcTestBase
+ {
+ [Fact]
+ public async Task GetAll_Test()
+ {
+ var result = await GetResponseAsObjectAsync>("/api/services/app/person/GetAll");
+ result.Items.Count.ShouldBeGreaterThan(0);
+ }
+ }
+}