Thursday 29 March 2012

Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role - Part 3

In previous posts, we have seen how to publish multiple Sub Sites and Virtual Directories in a single Web Role. In this post, I am going to walkthro’ how to publish multiple sites in a single Web Role.

This feature is more useful when we have multiple small sites that are not having heavy load. So we can publish them in a single Web Role and can use same instance for running multiple web sites. It will useful for consuming the cost compare to having separate Web Role for each small site.

But, one thing we note here is we use same application pool for all sites. So, it may impact the performance when the load becomes heavy.

Coming to the implementation point of view, we got two ways to publish multiple sites in a single Web Role.
  1. First way is to mention the port number for each site to run on. So each site will be run on different port number and will be accessible by providing the port number at the end of the cloud end point.
    Ex: http://samplemultiplesites.cloudapp.net (is equal to accessing http://samplemultiplesites.cloudapp.net:80 – site running in 80 port)
    http:// samplemultiplesites.cloudapp.net :81 (site running in 81 port)
  2. Second way is to use the host header.
    In some times we may configure custom domain name for Web Roles. So it can be accessible using the custom domain name (Ex: www.dotnettwitter.com/subsite) instead of using hostedserviceurl.cloudapp.net. We can provide this host header in the configuration file. So when any request comes from the browser to Web Role, it can able to identify which site needs to be routed for the request.
We will see both the methods. Let us start with the first method providing port number.

Configuring Multiple Sites using Port Number:

Creating the Project
Step 1: Create a Cloud Project in Visual Studio.
Step 2: As we are running multiple sites in a single role, we will keep a sample message in the Default.aspx page for understanding which site is running.
Open the Default.aspx and modify the page content to Web Role Application.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    Web Role Application
</asp:Content>

Adding a New Site

We will first add a New Web Site and try with adding Web Application next.

Step 1: Right click the project and select Add -> New Web Site.
Provide the path where the solution is stored with the web site name (Ex: WebSite1).
Step 2: To identify which site is running, open the Default.aspx page and change the content to WebSite1.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    WebSite1
</asp:Content>
Step 3: We will configure this new web site in to Azure project to run into cloud. So open the ServiceDefinition.csdef file and add another <Site> under <Sites> node and add an additional InputEndPoint under Endpoints node.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MultiSites" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole" vmsize="Small">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
      <Site name="WebSite1" physicalDirectory="../WebSite1">
        <Bindings>
          <Binding name="Endpoint2" endpointName="Endpoint2" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
      <InputEndpoint name="Endpoint2" protocol="http" port="81" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>
As you see in this configuration, we are adding a new Site node in which we are providing the PhysicalDirectory which is the path of the project. The PhysicalDirectory can be a relative path if possible (base path is cloud project folder) or otherwise can provide the actual path – both will work fine.
The binding name and endpoint name must be different from others to link with the port number.
Step 4: Run the project and you may get the following error.
This error is because of the compilation setting of the Web Site. So open the Web.Config file of the site added and change the debug option to true in the compilation node.
Step 5: Now run the project and see the output. There will be two browser open which has different port number in each.
Verify the message in the page.

Note: The port number assigned to the web site are different from what configured in the ServiceDefinition.csdef file. This may happend only in the development fabric and development fabric will assign to sites which are free ports (I hope, when we provide 80 for a site and it is been used then fabric will take the next port number in the sequence and assign). But when the role running in the Azure environment, the port number will be assigned what we had configured.

Adding a New Web Application

As we added a site, we can try with Web Application also. The steps are same.

Step 1: Right click the project and select Add -> New Project.
Provide the path where the solution.
Step 2: To identify which site is running, open the Default.aspx page and change the content to WebApplication1.
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    WebApplication1
</asp:Content>
Step 3: Now, open the ServiceDefinition.csdef file and add Site node and InputEndpoint node as we done before.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MultiSites" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole" vmsize="Small">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
      <Site name="WebSite1" physicalDirectory="../WebSite1">
        <Bindings>
          <Binding name="Endpoint2" endpointName="Endpoint2" />
        </Bindings>
      </Site>
      <Site name="WebApplication1" physicalDirectory="../WebApplication1">
        <Bindings>
          <Binding name="Endpoint3" endpointName="Endpoint3" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
      <InputEndpoint name="Endpoint2" protocol="http" port="81" />
      <InputEndpoint name="Endpoint3" protocol="http" port="82" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>
Step 4: Now run the project and see the output. You will be getting three browser open which has different port number in each.
As we had already seen in previous posts, we can even add multiple sub sites and virtual directories into the project if required.

Deploying the Application:

Deploying the WebRole is same as normally we do by using publishing from Visual Studio, uploading package using Management Portal, Power Shell script etc.,

Once the publishing done, each site can be accessible separetly using the port number as below.


As you seen in the browser address bar, each sites are accessed using the port number which it is running. For port 80, we don't need to mention the port.

Configuring Multiple Sites using Host Header:

We can even configure multiple sites using host header also instead of mentioning port number. As I dont have any sites running with a custom domain, I am unable to demo by publishing the site to Azure.

If anyone tried by host header, please comment on this blog. So it will be useful for us.

But the configuration will look like below.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MultiSites" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole" vmsize="Small">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
      <Site name="WebSite1" physicalDirectory="../WebSite1">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mydomain1.com" />
        </Bindings>
      </Site>
      <Site name="WebApplication1" physicalDirectory="../WebApplication1">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mydomain2.com" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>
As you see in this configuration, we are deploying two sites with different domain header and we have only one endpoint defined in this. So each request comes to the Web Role, it will redirect to corresponding site by domain header.

This configuration will work fine with Azure environment. But while in development, we required to test the site by accessing with domain name. So to test locally we need to add the host header in the hosts file located in %windir%\drivers\etc folder.

So open the %windir%\drivers\etc (i.e., C:\Windows\System32\drivers\etc in Vista/Win7) folder and open the hosts file and add the following line at end of the line.
127.0.0.1      www.mydomain1.com
127.0.0.1      www.mydomain2.com
Run the project and access using the domain name from browser and verify. Note: I have not tested yet using host header as I don't have host header for testing. So please comment if you face any issues when hosting with host header.

The other links on Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role:
  1. Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role - Part 1
  2. Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role - Part 2
  3. Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role - Part 3


0 Responses to “Publishing Multiple Sites, Sub-Sites & Virtual Directories in a single Azure Web Role - Part 3”

Post a Comment