mirror of https://github.com/abpframework/abp.git
15 changed files with 327 additions and 3 deletions
@ -0,0 +1,15 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
{ |
|||
[DependsOn(typeof(AbpMultiTenancyModule), typeof(AbpAspNetCoreModule))] |
|||
public class AbpAspNetMultiTenancyModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddAssemblyOf<AbpAspNetMultiTenancyModule>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.MultiTenancy |
|||
{ |
|||
public class AbpMultiTenancyModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddAssemblyOf<AbpMultiTenancyModule>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
|
|||
namespace Volo.Abp.Json |
|||
{ |
|||
public static class JsonExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Converts given object to JSON string.
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public static string ToJsonString(this object obj, bool camelCase = false, bool indented = false) |
|||
{ |
|||
var options = new JsonSerializerSettings(); |
|||
|
|||
if (camelCase) |
|||
{ |
|||
options.ContractResolver = new CamelCasePropertyNamesContractResolver(); |
|||
} |
|||
|
|||
if (indented) |
|||
{ |
|||
options.Formatting = Formatting.Indented; |
|||
} |
|||
|
|||
//options.Converters.Insert(0, new AbpDateTimeConverter()); //TODO: AbpDateTimeConverter?
|
|||
|
|||
return JsonConvert.SerializeObject(obj, options); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("Volo.Abp.AspNetCore.MultiTenancy.Tests")] |
|||
[assembly: AssemblyTrademark("")] |
|||
|
|||
// Setting ComVisible to false makes the types in this assembly not visible
|
|||
// to COM components. If you need to access a type in this assembly from
|
|||
// COM, set the ComVisible attribute to true on that type.
|
|||
[assembly: ComVisible(false)] |
|||
|
|||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|||
[assembly: Guid("2c282467-2cd5-4750-be1f-ca8bd8ecc6ea")] |
|||
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>2c282467-2cd5-4750-be1f-ca8bd8ecc6ea</ProjectGuid> |
|||
<RootNamespace> |
|||
</RootNamespace> |
|||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
|||
</ItemGroup> |
|||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|||
</Project> |
|||
@ -0,0 +1,33 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Modularity; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.AspNetCore.App |
|||
{ |
|||
[DependsOn(typeof(AbpAspNetMultiTenancyModule))] |
|||
public class AppModule : AbpModule |
|||
{ |
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
|
|||
app.Run(async (ctx) => |
|||
{ |
|||
var manager = ctx.RequestServices.GetRequiredService<IMultiTenancyManager>(); |
|||
|
|||
var dictionary = new Dictionary<string, string> |
|||
{ |
|||
["TenantName"] = manager.CurrentTenant?.Name ?? "<host>" |
|||
}; |
|||
|
|||
await ctx.Response.WriteAsync(dictionary.ToJsonString()); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.Net; |
|||
using System.Net.Http; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.TestBase; |
|||
|
|||
namespace Volo.Abp.AspNetCore.App |
|||
{ |
|||
public abstract class AppTestBase : AbpAspNetCoreIntegratedTestBase<Startup> |
|||
{ |
|||
protected virtual async Task<T> GetResponseAsObjectAsync<T>(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) |
|||
{ |
|||
var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode); |
|||
return JsonConvert.DeserializeObject<T>(strResponse, new JsonSerializerSettings |
|||
{ |
|||
ContractResolver = new CamelCasePropertyNamesContractResolver() |
|||
}); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetResponseAsStringAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) |
|||
{ |
|||
var response = await GetResponseAsync(url, expectedStatusCode); |
|||
return await response.Content.ReadAsStringAsync(); |
|||
} |
|||
|
|||
protected virtual async Task<HttpResponseMessage> GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) |
|||
{ |
|||
var response = await Client.GetAsync(url); |
|||
response.StatusCode.ShouldBe(expectedStatusCode); |
|||
return response; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.AspNetCore.App |
|||
{ |
|||
public class Startup |
|||
{ |
|||
public void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddApplication<AppModule>(); |
|||
} |
|||
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) |
|||
{ |
|||
app.InitializeApplication(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.App; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.MultiTenancy |
|||
{ |
|||
public class AspNetCoreMultiTenancy_Tests : AppTestBase |
|||
{ |
|||
private const string FakeUrl = "http://abp.io"; |
|||
|
|||
[Fact] |
|||
public async Task Should_Use_Host_If_Tenant_Is_Not_Specified() |
|||
{ |
|||
var result = await GetResponseAsObjectAsync<Dictionary<string, string>>(FakeUrl); |
|||
result["TenantName"].ShouldBe("<host>"); |
|||
} |
|||
|
|||
//TODO: Specify tenant in the header, cookie, url, querystring and so on...
|
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Net.Http; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.AspNetCore.Routing; |
|||
using Microsoft.AspNetCore.TestHost; |
|||
using Volo.ExtensionMethods; |
|||
using Volo.ExtensionMethods.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.TestBase |
|||
{ |
|||
public abstract class AbpAspNetCoreIntegratedTestBase<TStartup> |
|||
where TStartup : class |
|||
{ |
|||
protected TestServer Server { get; } |
|||
|
|||
protected HttpClient Client { get; } |
|||
|
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
protected AbpAspNetCoreIntegratedTestBase() |
|||
{ |
|||
var builder = CreateWebHostBuilder(); |
|||
Server = CreateTestServer(builder); |
|||
Client = Server.CreateClient(); |
|||
|
|||
ServiceProvider = Server.Host.Services; |
|||
} |
|||
|
|||
protected virtual IWebHostBuilder CreateWebHostBuilder() |
|||
{ |
|||
return new WebHostBuilder() |
|||
.UseStartup<TStartup>(); |
|||
} |
|||
|
|||
protected virtual TestServer CreateTestServer(IWebHostBuilder builder) |
|||
{ |
|||
return new TestServer(builder); |
|||
} |
|||
|
|||
#region GetUrl
|
|||
|
|||
/// <summary>
|
|||
/// Gets default URL for given controller type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TController">The type of the controller.</typeparam>
|
|||
protected virtual string GetUrl<TController>() |
|||
{ |
|||
return "/" + typeof(TController).Name.RemovePostFix("Controller", "AppService", "ApplicationService", "Service"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets default URL for given controller type's given action.
|
|||
/// </summary>
|
|||
/// <typeparam name="TController">The type of the controller.</typeparam>
|
|||
protected virtual string GetUrl<TController>(string actionName) |
|||
{ |
|||
return GetUrl<TController>() + "/" + actionName; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets default URL for given controller type's given action with query string parameters (as anonymous object).
|
|||
/// </summary>
|
|||
/// <typeparam name="TController">The type of the controller.</typeparam>
|
|||
protected virtual string GetUrl<TController>(string actionName, object queryStringParamsAsAnonymousObject) |
|||
{ |
|||
var url = GetUrl<TController>(actionName); |
|||
|
|||
var dictionary = new RouteValueDictionary(queryStringParamsAsAnonymousObject); |
|||
if (dictionary.Any()) |
|||
{ |
|||
url += "?" + dictionary.Select(d => $"{d.Key}={d.Value}").JoinAsString("&"); |
|||
} |
|||
|
|||
return url; |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
{ |
|||
"version": "1.0.0-*", |
|||
|
|||
"testRunner": "xunit", |
|||
|
|||
"dependencies": { |
|||
"AbpTestBase": "1.0.0-*", |
|||
"Volo.Abp.AspNetCore.MultiTenancy": "1.0.0-*", |
|||
"Microsoft.AspNetCore.TestHost": "1.1.0", |
|||
"Microsoft.AspNetCore.Routing.Abstractions": "1.1.0" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"netcoreapp1.1": { |
|||
"dependencies": { |
|||
"Microsoft.NETCore.App": { |
|||
"type": "platform", |
|||
"version": "1.1.0" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue