Introduction to Multi-Tenant Architecture, Page 3
The following code listing shows a page sending an email after a user registers for the site. Typically upon registration, some sort of email is sent to give that sense of confirmation or welcome message to the new user. If I had multiple tenants, I couldn't store the email settings in the Web.config because each site may want a different subject, body, and so forth. And, you definitely do not want to hard code for each case!!
namespace MultiTenantSite { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void CreateUserWizardControl_CreatedUser(object sender, EventArgs e) { // Create the Mail Message from the Cached App Settings // For the Tenant MailMessage confirmEmail = new MailMessage() { From = new MailAddress(new Data.AppSettings() ["Site.Registration.Email.From"]), Subject = new Data.AppSettings() ["Site.Reigstration.Email.Subject"], Body = new Data.AppSettings() ["Site.Registration.Email.Body"], }; // Create the SMTP Client and Send the Message SmtpClient emailSender = new SmtpClient("Some SMTP Host"); emailSender.Send(confirmEmail); } } }
Using a Content Management System
The next component to a multi-tenant application, a Content Management System (CMS), is optional but will help to display content dynamically on-demand for tenants that use the site. Designing a CMS can be an article within itself. Really, in this situation, you would want to use the CMS system to create content in a web-part format. You then can use these web parts interchangeably and on demand as you design your pages for a tenant. Typically, if the content is static with only different app settings and different App Themes, a CMS may not be needed.
To illustrate what I am talking about, assume I have a CMS system for a Multi-Tenant site where a database drives the system and stores web parts that are created are stored through some web part manager on the site. Now, in the actual solution, I have a footer control that is rendered on the master page, and on the footer I have three links: FAQ, Contact Us, and About. Each tenant that is using this base website may have different text that will need to be displayed for each link. With a Multi-Tenant site powered by CMS, I could create web parts for each different link for each tenant and set the PostBackUrl Property of each link button through the app settings.
Footer Markup
<table width="100%"> <tr> <td align="center"> <asp:LinkButton runat="server" ID="lnFAQ"> </asp:LinkButton> </td> <td align="center"> <asp:LinkButton runat="server" ID="lnContactUs"> </asp:LinkButton> </td> <td align="center"><asp:LinkButton runat="server" ID="lnAbout"> </asp:LinkButton> </td> </tr> </table>
Code Behind (Setup Links)
public partial class Footer : System.Web.UI.UserControl { protected void Page_Load(object sender, EventArgs e) { // Set the Post Back URLs for each link lnContactUs.PostBackUrl = GetRelativeCmsUrl("Site.Link.ContactUs"); lnFAQ.PostBackUrl = GetRelativeCmsUrl("Site.Link.FAQ"); } public static string GetRelativeCmsUrl(string configKeyName) { // return link to the CMS Page that Handles Web Parts, // Retrieve the ID of the Web Part from the // Cached App Settings return (String.Format("~/cms/page.aspx?ContentID={0}", new Data.AppSettings()[configKeyName])); } }
IIS Setup
The last piece to successfully implement a Multi-Tenant Web Site is setting up IIS to handle each website. This is a relatively simple concept, especially if you have already set up a basic ASP.NET website in IIS. To make this a little more complex and really demonstrate where Multi-Tenant architecture is handy, assume your server has only one public facing IP to register a website under. First, you will need to create a new website for each tenant. One problem with this: You need to assign an IP to each site but you only have one. A solution to this is to use host headers for each site, map each host header to the single IP, and then register the host headers with your respective DNS server.
