How To Operate Multiple Customer Sites In One Application

By Eliyahu Goldin 

Last edited December 24, 2006

It is quite a common scenario when the same web application has to represent multiple customer sites. On example is a hosted medical practice management system. Every practice subscribed for the service has its own presence on the web. It has a distinct set of customized parameters such as practice name, contact details, working hours and, most important, a separate practice database. The same host application has to distinguish between the practices and connect the customers to their environment.

If the number of the customer is limited to several dozens, it is easy to maintain the customer list in an XML file. Optionally, the file can contain a scheme enforcing only correct XML elements. Below is an example of a file with the XML schema and 2 customer records.

<?xml version="1.0" encoding="utf-8" ?>

<!DOCTYPE Customers [

  <!ELEMENT Customers (Customer*)>

  <!ELEMENT Customer (CustomerSupport?,DBConnection?)>

  <!ELEMENT CustomerSupport (Hours+)>

  <!ELEMENT Hours EMPTY>

  <!ELEMENT DBConnection EMPTY>

  <!ELEMENT DefaultDBCredentials EMPTY>

  <!ATTLIST Customer

        Id            ID    #REQUIRED

        Description   CDATA #REQUIRED

  >

  <!ATTLIST CustomerSupport

        Email    CDATA #IMPLIED

        Fax      CDATA #IMPLIED

        Phone    CDATA #IMPLIED

        TimeZone CDATA #IMPLIED

  >

  <!ATTLIST Hours

        Name CDATA #IMPLIED

        Time CDATA #IMPLIED

  >

  <!ATTLIST DBConnection

        Server         CDATA #REQUIRED

        Authentication (Sql|Windows) "Windows"

        Database       CDATA "CliniFlow"

        Username       CDATA #IMPLIED

        Password       CDATA #IMPLIED

  >

]>

 

<Customers>

    <Customer Id="p1" Description="Practice1 Portal">

        <CustomerSupport Email="support@practice1.com" Fax="234.567.8888" Phone="234.567.9999" TimeZone="EST">

            <Hours Name="Sun-Thu" Time="9:00 - 18:00" />

            <Hours Name="Fri" Time="9:00 - 13:00" />

        </CustomerSupport>

        <DBConnection Server="123.123.123.123" Authentication="Sql" Database="PracticeDB" />

    </Customer>

    <Customer Id="p2" Description="Practice2 Portal">

        <CustomerSupport Email="support@practice2.com" Fax="345.987.6666" Phone="345.987.5555" TimeZone="PST">

            <Hours Name="Mon-Fri" Time="9am - 5pm" />

        </CustomerSupport>

        <DBConnection Server="55.66.77.88" Authentication="Sql" Database="PracticeDB" />

    </Customer>

</Customers>

 

Customers have to supply their Id in the URL query parameter:

www.practiceportal.com?id=p1

The application gets the id and sets the customer information. The following code is a part of the application logon page. The code assumes that the customer records reside in the file Customers.xml in the application root directory. The page contains server-side html controls for customer description, email address, phone and fax numbers, time zone and a datagrid for support hours.

    protected void Page_Load(object sender, EventArgs e)

    {

        string customerId;

        // get customer data

        if (!String.IsNullOrEmpty (this.Request.Params["id"]))

            customerId = this.Request.Params["id"];

        if (!this.IsPostBack)

        {

            setupCustomer(customerId);

        }

    }

 

    private void setupCustomer(string customerId)

    {

        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

        doc.Load(String.Format("{0}\\{1}", this.Request.PhysicalApplicationPath, "Customers.xml"));

 

        System.Xml.XmlElement custNode = doc.GetElementById(customerId);

        if (custNode == null)

            throw new System.Xml.XmlException("Customer info not found");

 

        // customer info found, get parameters

        this.lblCustomerDescription.InnerText = custNode.Attributes["Description"].Value;

        this.Session["CustomerDescription"] = lblCustomerDescription.InnerText;

 

        System.Xml.XmlElement custSupportNode = custNode.FirstChild as System.Xml.XmlElement;

        this.lblEmail.InnerText = custSupportNode.Attributes["Email"].Value;

        this.lblPhone.InnerText = custSupportNode.Attributes["Phone"].Value;

        this.lblFax.InnerText = custSupportNode.Attributes["Fax"].Value;

        this.lblTimeZone.InnerText = custSupportNode.Attributes["TimeZone"].Value;

 

        System.Xml.XmlNodeList hourNodes = custSupportNode.ChildNodes;

        this.dgHours.DataSource = hourNodes;

        this.dgHours.DataBind();

 

        System.Xml.XmlElement dbConnectionNode = custNode.ChildNodes[1] as System.Xml.XmlElement;

        string server = dbConnectionNode.Attributes["Server"].Value;

        string database = dbConnectionNode.Attributes["Database"].Value;

        string authentication = dbConnectionNode.Attributes["Authentication"].Value;

        string connectionString = String.Format("Server={0};Database={1}", server, database);

        if (authentication == "Windows")

           connectionString += ";Integrated Security=SSPI";

        this.Session["ConnectionString"] = connectionString;

    }