Finbuckle / Finbuckle.MultiTenant

Finbuckle.MultiTenant is an open-source multitenancy middleware library for .NET. It enables tenant resolution, per-tenant app behavior, and per-tenant data isolation.
https://www.finbuckle.com/multitenant
Apache License 2.0
1.3k stars 265 forks source link

Does it work with Api controllers? #157

Closed skysgh closed 5 years ago

skysgh commented 5 years ago

Great potential.

I am trying it out on an ASP.Core 2+ site, that is mostly using ApiControllers routed by contention with a suffix of "api/{controllerName}" It works, usnig the default tenant -- but if I switch it to another tenantid, (eg: /api/tenant-2/{controllerName}) it returns 404. Is it meant to work only with View Controllers (as per your samples) or also with Apis and OdataControllers.

Thanks!

AndrewTriesToCode commented 5 years ago

hi @skysgh

It should work fine with API controllers. Looks like you using the route strategy, correct? Can you copy/paste your Startup.cs file and I can take a look?

skysgh commented 5 years ago

hi @achandlerwhite , Thanks for getting back to me :-) As per startup.cs

Route "defaultTenantedApi" is defined as

        routeBuilder.MapRoute(
            name: $"defaultTenantedApi",
            template: "{first_segment=}/api/{controller=Home}/{action=Index}/{id?}")

And a little earlier, I used:

        serviceRegistry
            .AddMultiTenant()
            .WithInMemoryStore(
                _configuration.GetSection("InMemoryStoreConfig"))
            //.WithStaticStrategy("wow")
            //.WithHostStrategy()
            //.WithRouteStrategy()
            .WithBasePathStrategy()
            .WithFallbackStrategy("tenant1");

Admittedly, I'm using Lamar (which prefers the use of ConfigureContainer(ServiceRegistry serviceRegistry) to set up services (as opposed to ConfigureServices(IServiceCollection serviceRegistry) but didn't think that would be a factor.

Also, there's Swagger in there somewhere, but thought that you probably had already made sure that your lib coexisted with it.

On a side note, I'm wondering if it is ok to stack Strategies (ie use both Host and BasePath) to handle cases where users haven't setup dns records yet?

Looking forward to getting this to work :-)

PS: the source code in the above link is not yet well documented...will get to it one day... but hope it almost makes sense to you! Thanks again for your help.

AndrewTriesToCode commented 5 years ago

Hi, so other stuff like swagger shouldn't interfere. I'm not sure about Lamar, but if regular ASP.NET Core works with it then this probably will too. You would see exceptions when running it it was unable to resolve DI.

With regard to strategies, I hope to support "chaining" and combining them in the future, but currently it do not. The only exception is fallback which can pair with any of the others. In dev if I use host strategy I will edit the /etc/hosts file on my machine to set subdomains for tenants... it is not ideal.

So just to help me understand where you are:

I recommend the Route strategy, but in ASP.NET Core 2.X you have to pass the same route config to WithRouteStrategy as to UseMvc. I recommend factoring it out into a method like so:

// In the ConfigureServices or equivalent
...AddMultiTenant().WithRouteStrategy(ConfigRoutes);
// In Configure or equivalent:
app.UseMvc(ConfigRoutes);
// In same file...
void ConfigRoutes(IRouteBuilder routeBuilder)
{
    // Make sure that a route parameter named __tenant__ is in there somewhere

    // Needed to get OData running.
    routeBuilder.EnableDependencyInjection();
    // Use our helpr methods for setting up routes:
    ConfigureRouteBuilderForTraditionalApiRoutes(routeBuilder);
 }

You may have already tried that, but I didn't see it in the file you linked.

Good luck, let me know how it goes, and keep asking questions. -Drew

skysgh commented 5 years ago

Hi Drew,

Whew. Got it to work. My issue is I was using Attribute routing on a base class (hence forgot its effect...oops). When I decorated it as follows, it worked with Route strategy, and the fallback strategy.

[Route(Apis.BasePath + "[controller]")]
[Route("{__tenant__=}/" + Apis.BasePath + "[controller]")]
[ApiController]
public abstract class AllModulesApiControllerBase : ControllerBase

Thanks for the pointers.

I eagerly await the ability to chain both Host and Route strategy... I imagine a user signing up for a free account, using Route, and if they registered for some form of Corporate account (with DNS records updated, and paying a bit of the cost towards a * cert, and probably a separate db connection string...) they could also get to their resources using a Host strategy.

Thanks again.

On Wed, 3 Jul 2019 at 04:06, Andrew White notifications@github.com wrote:

Hi, so other stuff like swagger shouldn't interfere. I'm not sure about Lamar, but if regular ASP.NET Core works with it then this probably will too. You would see exceptions when running it it was unable to resolve DI.

With regard to strategies, I hope to support "chaining" and combining them in the future, but currently it do not. The only exception is fallback which can pair with any of the others. In dev if I use host strategy I will edit the /etc/hosts file on my machine to set subdomains for tenants... it is not ideal.

So just to help understand where you are:

  • As just a basic check, if you use the static strategy does it work (obviously only returning the same tenant...)
  • Did base path strategy work for you?

I recommend the Route strategy, but in ASP.NET Core 2.X you have to pass the same route config to WithRouteStrategy as to UseMvc. https://www.finbuckle.com/MultiTenant/Docs/Strategies#route-strategy I recommend factoring it out into a method like so:

// In the ConfigureServices or equivalent ...AddMultiTenant().WithRouteStrategy(ConfigRoutes);

// In Configure or equivalent: app.UseMvc(ConfigRoutes);

// In same file... void ConfigRoutes(IRouteBuilder routeBuilder) { // Make sure that a route parameter named tenant is in there somewhere

// Needed to get OData running.
routeBuilder.EnableDependencyInjection();
// Use our helpr methods for setting up routes:
ConfigureRouteBuilderForTraditionalApiRoutes(routeBuilder);

}

You may have already tried that, but I didn't see it in the file you linked.

Good luck, let me know how it goes, and keep asking questions. -Drew

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Finbuckle/Finbuckle.MultiTenant/issues/157?email_source=notifications&email_token=AAI6CJQNCTQE2PNDVDEOFF3P5N4GTA5CNFSM4H4RRDTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZBYSRI#issuecomment-507742533, or mute the thread https://github.com/notifications/unsubscribe-auth/AAI6CJQE6ONB73CT5BC6MODP5N4GTANCNFSM4H4RRDTA .

skysgh commented 5 years ago

Thanks!

AndrewTriesToCode commented 4 years ago

@skysgh Hi there, just so you area aware the latest release allows chaining the strategy (not the host yet).