I am trying to migrate to Azure (including SQL Azure) with a multi-tenant ASP.NET MVC application. Each client receives its own database, which is autonomous, including all their credentials.
We can set the connection string for SqlMembershipProvider when initializing the SqlMembershipProvider object. However, subsequent requests to various subdomains (in the same session) do not change the connection string. I found an example where the implementation overrides the SqlMembershipProviders ConnectionString, but this is not possible in version 4.0 of the System.Web dll.
We could implement a single membership database and authenticate against it ... but we would like client credentials to be isolated in this SAAS model.
So the question is how to dynamically change the SQLMembershipProviders connection string for each query?
Web.config
<membership defaultProvider="TenantMembershipProvider"> <providers> <clear/> <add name="TenantMembershipProvider" type="ABC.Infrastructure.MultiTenancy.TenantMembershipProvider, ABC" connectionStringName="ApplicationServices" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Clear" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/> </providers> </membership>
TenantMembershipProvider.cs, which handles initialization
public class TenantMembershipProvider : SqlMembershipProvider { private SiteLinqSession _session; private MasterSession _masterSession; private static readonly Dictionary<string, Customer> _customers = new Dictionary<string, Customer>(); private static string _host; public override void Initialize(string name, NameValueCollection config) { base.Initialize(name, config); string connectionString = GetConnectionString(); FieldInfo connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic); connectionStringField.SetValue(this, connectionString); } private string GetConnectionString() { var headers = HttpContext.Current.Request.Headers["Host"]; string[] host = headers.Split('.'); _host = host[0]; if (_host == "127") _host = "demo"; var customer = GetSite(_host); return BuildTenantConnectionString(customer.ConnectionSetting); } private Customer GetSite(string host) { Customer customer;
source share