Another important milestone in my career started three years ago when I joined Tellago. I convinced my friend Jesus to hire me, and I would eventually move to the United States with my family to work in the company.  That never occurred for some personal things, but I fortunately had a chance to create an excellent team of very talented people in Argentina. I started myself working remotely from Argentina, and the things went so well for the company that we end up hiring more than 15 great architects down here in Argentina.  Creating this team was a very interesting and completely new challenge in my career.

I also got involved in a lot of interesting projects, and what is more important, I had a chance to work and met great people, which is what it really worth it.

However, a month ago, I decided it was about time to start a personal project with a good friend of mine, and that’s how AgileSight was born. Although the initial conception of the company was to create software products, we will also offering software consulting and development services. I am definitely very excited to be part of this new venture and face all new kind of challenges ahead.

My first assignment in AgileSight couldn’t be better as I will be working in the next Web Mobile Guidance project (Liike project) with the Microsoft Patterns & Practices team.

Posted by cibrax | 1 comment(s)
Filed under: ,

Limited connectivity is one of the main challenges in web mobile. The stateless nature of http causes that  content  and associated static files like scripts or images be transmitted over the wire every time a page is fully refreshed (assuming http caching is not implemented correctly). Diverse techniques have emerged over the years to solve part of that problem by using the browser AJAX support. One of these techniques, which drastically changed the way we develop web applications is know as single page applications.

A single page application design assumes that good part of the website layout is fixed and there are a few placeholders for showing dynamic content. The layout and associated files can be download once, and the rest can be dynamically changed using AJAX calls to a backend Web API.    

There are also a few improvements that can be made like caching all the static content and associated files, and use client templates to remove all the overhead involved with downloading html markup on every AJAX call. By using client templates (e.g. JQuery templates, JSRender, Mustache) , only the data (usually JSON data) is negotiated with the backend, and the templates can be cached as static content as well.

In the area of web mobile, it is pretty important to optimize the use of the available bandwidth to support scenarios where the connectivity is very unreliable or limited data plans are used. This is exactly where single page applications make a lot of sense. As this kind of application makes a heavy use of javascript for DOM manipulation, it might not be ideal for all kind of mobile devices (the device should support DOM manipulation and XHR).

I personally think this kind of architecture for a web application will become a common norm now that we have devices with web support everywhere.

Posted by cibrax | 4 comment(s)
Filed under: ,

One common problem with the naming convention and default routing mechanism in ASP.NET MVC is that we tend to group actions in a controller for sharing an URL space.  This basically leads to complex controllers with a lot of unrelated methods that break the SOLID principles.  Too many responsibilities in a simple class affects maintainability in the long run and causes secondary effects that complicates unit testing. For example, we usually end up with class constructors that receives too many dependencies as it is discussed here in SO.

A service façade or a service locator are not the solution for this problem either. I personally think the solution here is to use controllers with fewer responsibilities and define the right routing in case you want to share the URL space. There are some discussions around the idea of using what was called controller-less actions, in which a controller only performs a single thing. Without going to that extreme, we can use a more resource oriented approach for assigning responsibilities to a controller.  A resource in http is uniquely identified by an URI  and can be manipulated through an unified interface with http verbs. Although some verbs do not make much sense when working with a browser like “delete” or “put”, we can replace those with “post”.

Implementing a delete action with an http get is definitely wrong, as an http get should be idempotent.

Let’s start an example by defining a simple scenario for managing a set of customers. We can initially define two resources, Customers for performing actions in the collection, and Customers/{id} for performing actions in a single customer. Although they both share the same URL space “Customers”, it does not mean we need to implement all the functionality in a single controller called “Customers”. We can still have a “CustomersController” for the collection, and a “CustomerController” for the individual customers. We can use routing for share the same URL and still forward the requests to the right controller.

We can define the following operations in the “CustomersController”,

  • Add (GET Customers/Add): Retrieves the Html form representation for creating a new customer
  • Add (POST Customers/Add): Receives a representation (encoded in the form) for creating a new customer in the collection
  • Delete (POST Customers/{id}/Delete: Removes a customer from the collection
  • Index (GET Customers): Retrieves a Html view representing a list of customers
public class CustomersController : Controller
{
    ICustomerRepository repository;
 
    public CustomersController()
        : this(new CustomerRepository())
    {
    }
 
    public CustomersController(ICustomerRepository repository)
    {
        this.repository = repository;
    }
 
    public ActionResult Index(string filter = null)
    {
        IEnumerable<Customer> customers = null;
 
        if (!string.IsNullOrEmpty(filter))
        {
            customers = this.repository.GetAll()
                .Where(c => c.FirstName.Contains(filter) || c.LastName.Contains(filter));
        }
        else
        {
            customers = this.repository.GetAll();
        }
        
        return View(customers);
    }
 
    [HttpGet]
    public ActionResult Add()
    {
        return View();
    }
 
    [HttpPost]
    public ActionResult Add(Customer customer)
    {
        if(ModelState.IsValid)
            this.repository.Add(customer);
 
        return RedirectToAction("Index");
    }
 
    [HttpPost]
    public ActionResult Delete(int id)
    {
        this.repository.Delete(id);
 
        if (Request.IsAjaxRequest())
            return new HttpStatusCodeResult((int)HttpStatusCode.OK);
 
        return RedirectToAction("Index");
    }
 
}

The “CustomerController” can have the following operations:

  • Get (GET Customers/{id}): Retrieves an Html form representing an specific customer
  • Update (POST Customers/{id}): Receives a representation (encoded in the form) for updating the customer
public class CustomerController : Controller
{
    ICustomerRepository repository;
 
    public CustomerController()
        : this(new CustomerRepository())
    {
    }
 
    public CustomerController(ICustomerRepository repository)
    {
        this.repository = repository;
    }
 
    [HttpGet]
    public ActionResult Get(int id)
    {
        var customer = this.repository.GetAll()
            .Where(c => c.Id == id)
            .FirstOrDefault();
 
        if (customer == null)
            return new HttpStatusCodeResult((int)HttpStatusCode.NotFound);
 
        return View(customer);
    }
 
    [HttpPost]
    public ActionResult Update(Customer customer)
    {
        if (ModelState.IsValid)
            this.repository.Update(customer);
 
        return RedirectToAction("Index", "Customers");
    }
 
}

This is how the routing table looks like,

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    //This map is required so the Add segment is not used as {id}
    routes.MapRoute(
      name: "CustomerAdd",
      url: "Customers/Add",
      defaults: new { controller = "Customers", action = "Add" }
      );
 
    routes.MapRoute(
       name: "CustomerGet",
       url: "Customers/{id}",
       defaults: new { controller = "Customer", action = "Get" },
       constraints: new { httpMethod = new HttpMethodConstraint("GET") }
       );
 
    routes.MapRoute(
        name: "CustomerUpdate",
        url: "Customers/{id}",
        defaults: new { controller = "Customer", action = "Update" },
        constraints: new { httpMethod = new HttpMethodConstraint("POST") }
        );
 
    routes.MapRoute(
        name: "MVC Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
 
   
}

You can override the default route for “Customers/{id}” for getting or updating an specific customer by using an http method constraint. I also added the first  route for adding a new customer so the “Add” segment is not used as the “{id}” wildcard.

As you could see, we could split all the responsibilities in two controllers, which look simpler at first glance. In conclusion, you don’t need to assume the same URL means the same controller.

The “delete” action is implemented as an http post. This can be sent from the browser by using an Ajax call or a Http form. For example, the following code shows how to do that using a JQuery Ajax call.

@Html.ActionLink("Delete", "Delete", new { id = item.Id }, new { @class = "delete" })
<script type="text/javascript" language="javascript">
   1:  
   2:     $(function () {
   3:         $('.delete').click(function () {
   4:             var that = $(this);
   5:             var url = that.attr('href');
   6:  
   7:             $.post(url, function () {
   8:                 alert('delete called');
   9:             });
  10:  
  11:             return false;
  12:         });
  13:     });
</script>
The code is available for download from here
Posted by cibrax | 4 comment(s)
Filed under: , ,

Microsoft Patterns & Practices has recently started a new project whose codename is “Liike” (pronounced as LEEE-keh) for delivering guidance and a reference application in the mobile web space. As many of the recent initiatives started by different teams in Microsoft, this project will also be hosted in GitHub under http://liike.github.com/. All the artifacts, patterns and code generated during the project will be shared as part of that project.

Html5 and the rise of mobile devices have contributed to make Web Mobile one of the hot topics nowadays. Embarking in a new project for implementing a web mobile application can be a bit cumbersome without proper documentation or knowledge of proven practices. This project will try to address many of the concerns you might have by showing different patterns or solutions that can be applied in the context of web mobile, and how those solutions get reflected in real code with the Microsoft stack. The idea is not produce reusable code, but a reference application that people can explore.

As any of projects in MS Patterns & Practices, Microsoft does not have the final word on any of the discussed topics and a lot of feedback is received. They also have a team of external advisors with a bunch of talented people that have an extensive background working in this space.

Your help is always very valuable, so you can also contribute to the project by joining to the advisory team or giving feedback through user voice here.  

Posted by cibrax | with no comments
Filed under: , , ,

Faye is a simple Http Pub/Sub server initially implemented by John Coglan in Ruby, and also later ported by himself to Node.js. The version for Node.js implements the Bayeux protocol, which at first glace, many of us known as http long polling.

This project just represents another alternative to Socket.IO, which also works for client applications that are not necessarily implemented within a web browser.  As many http pub/sub engines out there, Faye also uses the idea of channels for routing messages, and it ships with two message repositories out of the box, a repository that runs in memory and a repository that stores the messages in REDIS.

On other hand, we have “IISNode”, one the coolest projects announced by Microsoft to host Node.js applications in IIS. One of the things you can do with IISNode is to run websites implemented with express or connect, and Faye can also be attached to an application implemented with connect, so we can this use this common denominator to mount a Faye server with IISNode.

This is also relatively attractive if you want to run your own pub/sub server in Windows Azure using IISNode as it was announced today

The code for the Faye server looks as follow (server.js),

var faye = require('faye'),
       connect = require('connect');
var server = connect.createServer(
    connect.staticCache()
);
  
var ROOT_ADDRESS = '/node/faye-node/myapp/';
 
server.use(ROOT_ADDRESS + 'static', connect.static(__dirname + '/static'));
server.use(ROOT_ADDRESS, function(req, res) {
  res.setHeader('Content-Type', 'text/html');
  res.end(process.env.PORT);
});
 
var bayeux = new faye.NodeAdapter({mount: ROOT_ADDRESS + 'faye', timeout: 45 });
 
bayeux.attach(server);
 
server.listen(process.env.PORT);

A few things to notice here,

  • The listen port is provided by IIS through the PORT environment variable.
  • The application is hosted in IIS under the virtual directory “node/faye-node”, and “myapp” is just a mapping I defined for the application using connect.
  • The Faye server is configured to listen to request messages on “node/faye-node/myapp/faye”

If you take a look at the web.config file for this application, the URL routing module is used to redirect all the traffic to “myapp” to this node application (server.js)

<configuration>
  <system.webServer>
 
    <!-- indicates that the hello.js file is a node.js application 
    to be handled by the iisnode module -->
 
    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode" />
    </handlers>
    
     <rewrite>
      <rules>
        <rule name="myapp">
          <match url="myapp/*" />
          <action type="Rewrite" url="server.js" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Once you have the server up and running, you can configure several clients to send or subscribe messages to/from the Faye server. This is how a client application implemented in Node.js looks like,

var faye = require('faye');
 
var client = new Faye.Client('http://localhost/node/faye-node/myapp/faye',{
     timeout: 120
 });
 
client.subscribe('/one', function(message) {
    console.log('something received: ' + message.result );
 });
 
var publication = client.publish('/one',{ result: 'other message from one'});
 
publication.callback(function(){
    console.log('message sent');    
    client.disconnect();
});
 
publication.errback(function(err){
    console.log(err);
});
 

As you can see, the complete URL is used on the client side to connect to the server. A client for Faye can also be implemented within a browser,

<html>
  <head>
    <script type="text/javascript" 
        src="http://localhost/node/faye-node/myapp/faye.js">
        </script>
    <script type="text/javascript" 
        src="http://localhost/node/faye-node/static/jquery.js">
        </script>
  </head>
  <body>
    <script type="text/javascript">
      
      var client = new Faye.Client('http://localhost/node/faye-node/myapp/faye',{
        timeout: 120
      });
      
      function publish() {
    var publication = client.publish('/one',{ result: 'message from one'});
        publication.callback(function(){
          alert('message sent');
        });
      }
    </script>
    <span onclick="publish();">Click me!</span>
    <h1>Home.html</h1>
    <ul class="container">
    </ul>
  </body>
</html>

Faye will provide an URL for downloading the client library in the browser (myapp/faye.js).

Download the complete sample from here

Posted by cibrax | 2 comment(s)
Filed under: , , ,

If you are using SQL Azure nowadays, you probably know that there are only a few alternatives for making backups of your existing data.

  • You can use SQL Azure Data Sync, which provides bi-directional data synchronization and data management capabilities allowing data to be easily shared across SQL Azure databases within multiple data centers. This implies you need at least one additional database for backing up your data, and SQL Azure databases are not necessarily cheap to keep them around without any functional use.
  • You can use third party tools like the ones offered by Cerebrata or RedGate to synchronize SQL Azure databases with On-Premises databases or dump your data to files

Or you can use Hgdbackup, an OS alternative started by Bertrand Le Roy that uses the SQL BCP command line tool to persist your database data into text-based files.  As this was exactly what I was needing for an Azure project, I decided to contribute some code to that tool for storing the backup files to the Blob Storage in Azure. Therefore, you can now specify in the tool the Azure storage account you want to use to store your backup files, or restore your database from. 

The tool uses the raw REST API for the Blob Storage service so the Azure SDK or the binaries included on it are not required. This means the tool is very simple to distribute or run in a server with minimal requisites.

The following examples illustrates how you can run the tool for making a new backup or restore an existing database.

Backup Example

Hgdbackup.exe /S:tcp:YOUR_Server.database.windows.net /D:YOUR_DB /U:YOUR_USER /P:YOUR_PASSWORD /A:YOUR_BLOB_ACCOUNT /K:YOUR_BLOB_KEY /T:"Server={0},1433;Database={1};User Id={2};Password={3};Trusted_Connection=False;Encrypt=True;"

Restore Example

Hgdrestore.exe /S:.\SQLExpress /D:YOUR_DB  /C:YOUR_BLOB_CONTAINER /A:YOUR_BLOB_ACCOUNT /K:YOUR_BLOB_KEY

The backup tool supports an additional argument “C:” for passing the container where you want to store the text files with the data. If you don’t provide a container name, the tool will generate a new container for you.

The good thing about this tool is that it is an open source initiative so you are free to contribute, give feedback or improve it as I did with this support for the blob storage.

Posted by cibrax | with no comments
Filed under: , ,

We have been working a lot lately with PowerShell as part of our star product at Tellago Studios, “Moesion”. One of the main features we provide in Moesion is the ability to execute PowerShell commands remotely in a given server using a web mobile interface (You can read more in my previous post about Moesion).

One of the things we realized in all this time is that PowerShell lacks of a central repository where IT guys or we, the developers, can easily grab and reuse commands.  All the commands or modules are basically spread across multiple places or websites, like personal blogs, TechNet or CodePlex projects to name a few making the search of them very hard. You are usually limited to use your favorite search engine and copy what you find. In addition, there is not an easy way to reuse, extend or version these commands, which also limits any contribution that you could make to the community. 

My friend Jose wrote a great post the other day about the importance of reusing PowerShell modules, and what is the mechanism to reuse them. Jose, however, based his post in a custom implementation using a GIT repository for storing the modules.

We have NuGet in the .NET platform for sharing and reusing existing libraries or code, so why can’t just leverage it for reusing PowerShell modules as well ?. Some teams in Microsoft are using NuGet for distributing libraries and binaries so it would be a great thing for all of us if they also distribute the scripting interfaces in PowerShell using NuGet. This applies to the .NET OS community as well.

In fact, it looks like Andrew Nurse had the same idea and implemented a project for this in BitBucket, PsGet.

Posted by cibrax | with no comments
Filed under: , ,

Deployment is considered today as one of the major pain points in the Windows Azure platform.  A simple application deployment today can take around 20 or 30 minutes to complete, and to make the things even worse, there is not support for partial updates meaning that a simple change requires a complete upgrade or deployment.  The Windows Azure team has recently introduced the support for web deploy in the platform to deal with this issue. Using Web Deploy, you can deploy a complete application or part of it in an existing web role instance in a matter of seconds, which is a huge improvement to what we had so far. 

However, Web Deploy only supports deployments to a single instance in a web role.  If your web role is made up of two or more instances, which is the typical configuration instances to be covered by a 100% uptime, web deploy won’t work in that scenario.

This is where the Windows Azure Accelerator for Web Roles enters the scene. This is a project created by the Developer and Platform evangelism team in Microsoft for deploying one or more websites across multiple Web Role instances using Web Deploy.  It basically explores the idea of using a single web role for hosting multiple web sites, simplifying the deployment and minimizing costs.

As part of the project, you will find an MVC application that you can deploy in one hosted service in Azure.  That application provides an visual administrative interface to define and manage the websites or applications you want to host in the web role. 

As you will be managing multiples websites internally hosted in a web role, you will need to assign different http host headers to those web sites and have domains or CName records already set for those. For example, if the address of your hosted service is cibrax.cloudapp.net (The MVC application will be listening on this address), you can later set some CName records in your domain for redirecting users to the hosted service address (www.mydomain.com –> cibrax.cloudapp.net)

Therefore, you won’t able to use this project if you don’t own a public domain in which you can set up some CName records.

Another important aspect of the accelerator is that it replicates your websites across all the instances of the web role breaking that big limitation in Web Deploy. It internally uses the blob storage to perform this replication.

In a traditional web application hosted in Azure, you will want to have some configuration settings as part the hosted service configuration so they can easily be changed without deploying your application completely, which is what it would happen if you have everything in the web.config file for example. This is no longer needed with the accelerator as you can now deploy an application from scratch in a few seconds.

Posted by cibrax | with no comments
Filed under: ,

Moving your application to the cloud might not be easy as it sounds. The typical sample we always see in documentation or demos about an ASP.NET application created from the Visual Studio template and deploy it in Azure as a package is definitely very far from reality. There are multiple factors that can affect the response time and availability of your applications in the cloud but you can not easily see until you embark on a real project. Application distribution and deployment is one of those factors, and the one we are going to discuss in this post.

Windows Azure uses the idea of regions to manage the physical distribution of your applications and data. A region in a nutshell represents a Microsoft data center where you can deploy your application or part of it. Nowadays, you can find multiple regions spread across the globe in places such as North America, Europe and Asia.

There is another abstraction layer on top of regions called "Affinity Groups", which simply tells the Fabric controller to do its best to ensure groups of related services are deployed in close proximity whenever possible to ensure optimization for inter-app communication. For example, in a typical web application with a database,  you will want to deploy the web application as close as possible to the database server. 

Finally, another important concept you need to understand in this deployment model is the idea of “hosted service”. A hosted service basically represents an unit of deployment associated to a public DNS in the cloud. You deploy your applications in a hosted service, which is also tied to a region or affinity group. What Azure gives you is a public address for reaching that hosted service in the cloud, which is “[you app name].cloudapp.net” for applications hosted in the production environment and an auto generated guid for applications hosted in the staging environment. You can also think in a hosted service as a load balancer that forwards requests from that public address to one of the instances or VMs associated to it.

Let’s discuss the aspects you need to consider for selecting the right regions for deploying your application.

  • Network latency: reducing the network latency is very important as it will impact directly on the response time for your applications. You will want to have your users as close as possible physically from your applications and data. For example, if you have some potential users in the US and Europe, you will want to deploy two exact replicas from your application and data in the US and Europe data centers. As you might guess, this is not as easy as it sounds and there are a lot of challenges you need to address, how you can effectively redirect the users to the right region, or how you can synchronize your data across regions are typical questions or concerns you have to tackle first.
  • Availability: you will want to have your applications available all the time. Many things can happen, but you need to understand that a region or data center might become offline and your application should be prepared to handle that scenario. Your applications and data should be replicated across multiple regions to not be affected when things like this occur.   

Microsoft already offers a set of tools or technologies you can use to address these two aspects, so let’s discuss some of them in detail in the next paragraphs.

Windows Azure Traffic Manager

While this technology is still a CTP and not available for all public in general, it will provide several methods for distributing internet traffic among two or more hosted services in different Windows Azure datacenters. It is in essence a distributed DNS service that knows which Windows Azure Services are sitting behind the traffic manager URL and distributes requests based on different policies  or modes you can configure. It will initially support three modes, “Failover”, “Performance” and “Round-Robin”.

In the “Failover” mode,  all the traffic is redirected to a single hosted service, unless it fails. If the redirection fails because the hosted service is not longer available,  it then directs the traffic to the hosted service configured as failover. For example, you can configure the South Central US region as a backup for the North Central US region and vice versa. If any of those regions go offline, the other one will take its place.

In the “Performance” mode, all traffic is mapped to the hosted service “closest” to the client requesting it.  For example, this will direct users from the US to one of the US datacenters and European users will probably end up in one of the European datacenters.

Finally, in the “Round-robin” mode, the traffic is distributed in a round robin fashion across several hosted services configured in the policy.

As you can see, this tool only tackles the two aspects mentioned before from the point of view of traffic redirection. However, you also need to make sure the data is also consistently available in all the regions, and that’s something this tool won’t solve. For example, if the users are redirected from North US to Central US, you need to make sure the data they get access look the same.

Content Delivery Network (CDN)

You can imagine the Windows Azure Content Delivery Network as a huge http cache spread across the globe for content such as images, files, scripts, or static html to name a few. You can either configure CDN for a blob storage account or an http endpoint in your application (and endpoint with an url ending in “cdn”, for example xxx.cloudapp.net/cdn). All that content will be cached in the nodes that are part of the network using standard Http caching. The CDN will serve later the cached copy closest to the user requesting it, improving in this way the response time.

There are today more than 18 locations or nodes globally (United States, Europe, Asia, Australia and South America) and this number keeps growing.

SQL Azure Data Sync

While the Azure Table Service already provides some built-in support for crash recovery based on the idea of partitions that are replicated across different nodes (in different sub regions, for example North US and Central US), a SQL Azure database is not prepared for that scenario.  If you also use something like the Traffic Manager to redirect users to the closest data center, you probably would want to have all the databases in the different regions in sync between them making all this process transparent to the user.

If you want to support that scenario, the SQL Azure Data Sync is the tool that will help you in this matter. In a nutshell, SQL Azure Data Sync is a cloud-based data synchronization service built on the Microsoft Sync Framework technologies. It provides bi-directional data synchronization and data management capabilities allowing data to be easily shared across SQL Azure databases within multiple data centers.

There are a few things you will have to configure in this tool

  • The databases you want to keep in sync, and also the tables and columns in those databases
  • The schedule or frequency for doing the synchronization.
  • How you want to resolve any conflict that might occur during the synchronization.

As you can see, the combination of this tool with the traffic manager will help you to keep applications and data in sync between different region for the most common scenarios.

Posted by cibrax | with no comments
Filed under: ,

A hosted service in azure is typically assigned with two public addresses, one for the production environment with a DNS name ending in cloudapp.net such as [your name].cloudapp.net and an auto generated DNS name for the staging environment such as 4969aae4e18f4699aa88223e1e73ba8e.cloudapp.net. There are multiple reasons you might want to map your custom domain name to these public names in Azure, but these are the most common ones I can imagine,

  • You don’t want to tie your websites to a single cloud hosting vendor such as Microsoft
  • You host multiple websites in a single hosted service in azure, so a single address such as xxx.cloudapp.net  does not make sense anymore. In that scenario, you need to use different port numbers for the websites or use host headers, which is the typical solution. For example, you might want to map [your name].com and [your other name].com to two different websites in the same hosted service (xxx.cloudapp.net).
  • You want to map a single domain to multiple hosted services in azure in different regions, and use geographic DNS routing to balance traffic. For example, you might have xxx-us.cloudapp.net for a hosted service in the US and xxx-eu.cloudapp.net for another hosted service in Europe but a single domain [your name].com that automatically routes the traffic according to the source of the http requests.

In the two first cases, the use of CName records in a domain that you own will work for redirecting all the traffic from there to the hosted service in Azure. The last one might require an additional DNS service like the Traffic Manager in Azure or Route53 in Amazon. 

It’s common nowadays for most websites to host two different versions of the same portal for mobile devices and regular browsers, which basically fits in the scenario I described as number #2. We can not use the default addressing schema in Azure anymore because the IIS instance running in hosted service wouldn’t know how to route the traffic to the right portal. However, this can be resolved with a combination of CName records at DNS level and host headers at IIS configuration level.

Configuring different host headers for the websites in IIS is easy to achieve with the use of multiples bindings and endpoints at configuration level.

<Sites>
  <Site name="Mobile" physicalDirectory="..\xxx">
    <Bindings>
      <Binding name="HttpIn" endpointName="HttpIn" hostHeader="m.xxx.com" />
      <Binding name="HttpInStaging" endpointName="HttpIn" hostHeader="stagingm.xxx.com" />          
    </Bindings>
  </Site>
  <Site name="Portal" physicalDirectory="..\xxx">
    <Bindings>
      <Binding name="HttpIn" endpointName="HttpIn" hostHeader="www.xxx.com" />      
      <Binding name="HttpInStaging" endpointName="HttpIn" hostHeader="staging.xxx.com" />
    </Bindings>
  </Site>
</Sites>

The snippet above illustrates how the Service Definition should look for supporting two different web sites for the mobile site and regular web site. An important thing to notice in the configuration is that I also included the host headers for staging, so you can test staging as well before making the switch to production. This means will require a different set of CName records for staging and production,

  • The “www” and “m” records will point to the production website in azure, xxx.cloudapp.net
  • The “staging” and “stagingm” records will point to the auto generated address for staging in azure

A CName record for the auto generated address in staging is not a good thing as it gets generated every time you create a new staging deployment. However, there is no other good way to fix in the meantime unless you actually do not include this definition for staging and you test everything local by pointing your windows host file to the IP address in staging (For instance, www.xxx.com [Staging IP Address] and m.xxx.com [Staging IP Address]).

The service definition can not be changed or updated once the deployment has been completed so make sure to get it right in the first place.

Posted by cibrax | with no comments
Filed under: , ,
More Posts Next page »