.NET Core单应用单数据库实现多客户独立域名产品列表站点方案咨询
Absolutely feasible—this is a tried-and-true pattern for SaaS-style multi-tenant setups using a single .NET Core app instance, and you’ve already got the right core ideas in place. Let’s break down how to make this work smoothly without managing multiple IIS sites.
Core Concept: Tenant Identification via Domain
The key here is tying each customer’s domain to a "tenant" record in your database. This record will store:
- The customer’s domain (e.g.,
customer1.com,shop.customer2.net) - Custom text content (site title, descriptions, call-to-action text)
- Template preferences (if you offer multiple design options)
- Any product filtering rules (if the customer should see a subset of your product catalog)
Step 1: Add Tenant Recognition Middleware
.NET Core’s middleware pipeline makes it easy to intercept incoming requests and identify the tenant based on the Host header. Here’s a simplified example:
public class TenantMiddleware { private readonly RequestDelegate _next; public TenantMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, YourDbContext dbContext) { // Extract the domain from the request (ignore port if present) var requestedDomain = context.Request.Host.Host; // Look up the tenant in your database var tenant = await dbContext.Tenants .FirstOrDefaultAsync(t => t.Domain.Equals(requestedDomain, StringComparison.OrdinalIgnoreCase)); if (tenant == null) { // Reject unrecognized domains context.Response.StatusCode = StatusCodes.Status403Forbidden; await context.Response.WriteAsync("This domain is not authorized to access this service."); return; } // Store the tenant in HttpContext for use in controllers/views context.Items["CurrentTenant"] = tenant; await _next(context); } } // Register the middleware in Program.cs (before routing!) app.UseMiddleware<TenantMiddleware>();
Step 2: Render Customized Content with Templates
With the tenant identified, you can serve pre-defined Razor templates populated with the customer’s custom content and product data:
Controller Example
public class PublicProductListController : Controller { private readonly YourDbContext _dbContext; public PublicProductListController(YourDbContext dbContext) { _dbContext = dbContext; } public async Task<IActionResult> Index() { var currentTenant = HttpContext.Items["CurrentTenant"] as Tenant; if (currentTenant == null) return Forbid(); // Fetch products based on the tenant's rules (e.g., all products, or a filtered subset) var products = await _dbContext.Products .Where(p => p.IsPublic && p.TenantId == currentTenant.Id) // Adjust filter as needed .ToListAsync(); var viewModel = new PublicProductListViewModel { Products = products, SiteTitle = currentTenant.CustomSiteTitle, SiteDescription = currentTenant.CustomSiteDescription, CustomFooterText = currentTenant.CustomFooterText }; // Use a pre-defined view template return View("ProductListTemplate", viewModel); } }
View Template Example (ProductListTemplate.cshtml)
@{ var vm = Model as PublicProductListViewModel; } <!DOCTYPE html> <html> <head> <title>@vm.SiteTitle</title> <meta name="description" content="@vm.SiteDescription"> <!-- Link to your shared CSS for the pre-defined design --> <link rel="stylesheet" href="/css/product-list-template.css"> </head> <body> <header> <h1>@vm.SiteTitle</h1> <p class="subtitle">@vm.SiteDescription</p> </header> <main> <div class="product-grid"> @foreach (var product in vm.Products) { <div class="product-card"> <h3>@product.Name</h3> <p>@product.ShortDescription</p> <span class="price">$@product.Price.ToString("N2")</span> </div> } </div> </main> <footer> <p>@vm.CustomFooterText</p> </footer> </body> </html>
Step 3: Configure IIS for Multiple Domains
No need for separate IIS sites! Just add all customer domains as bindings to your single .NET Core application site:
- Open IIS Manager, navigate to your app’s site.
- Right-click > Edit Bindings.
- Add a new binding for each customer’s domain (choose HTTP/HTTPS, enter the domain, and select the appropriate SSL certificate if using HTTPS).
Don’t forget to ensure each customer’s DNS records point to your server’s public IP address.
Critical Considerations
- Security: Always validate the incoming domain against your tenant database to prevent spoofing. Never trust the
Hostheader blindly. - Caching: When caching content (e.g., product lists), include the tenant ID in your cache keys to avoid serving the wrong customer’s data.
- Static Assets: If customers need custom logos or images, store them in a tenant-specific directory (e.g.,
wwwroot/tenants/{tenantId}/assets) and reference them dynamically in your views. - HTTPS: Use a multi-domain SSL certificate (or Let’s Encrypt for free auto-renewing certificates) to cover all customer domains.
Final Verdict
Your plan is not just feasible—it’s a clean, scalable approach that avoids the overhead of managing multiple app instances or IIS sites. By leveraging .NET Core’s middleware and a tenant-aware database design, you can deliver customized, domain-specific product lists with minimal complexity.
内容的提问来源于stack exchange,提问作者Adam Gajdečka

