среда, 17 октября 2012 г.

Html Print - Prevent Images from being Split

Technically there is:

img { page-break-inside: avoid; }

On the other hand, browsers that tend to split images probably don't support
the page-break-inside property (which is generally poorly supported).

There's no good solution. You could say page-break-before: always for the
image, which is well-supported, but that would be an unconditional break. A
small change in paper size or formatting of preceding content (due to
something in a user style sheet, for example) could easily cause a natural
page break a little before the image, and then you would have a few lines of
text on a fresh page, then the page break you asked for...

четверг, 11 октября 2012 г.

WebMatrix - jQuery Cascading Dropdown Lists


I have looked at cascading dropdown lists with WebMatrix previously, but the approach I featured demonstrated the use of jQuery Templates. At the time, the jQuery Templates project looked promising, but since then, the jQuery team have decided not to take them beyond beta stage. So the reason for this article is to illustrate a more "traditional" jQuery approach to managing cascading dropdown lists when developing ASP.NET Web Pages using WebMatrix.

The article makes use of the ubiquitous Northwind database (SQL Server CE 4.0 version) and initially presents the user with a dropdown containing a list of categories drawn from the database. Once the user has selected a category, a second dropdown list is populated with products within that category without the page being posted back to the server. The article will show how to use jQuery to achieve this, using either standard HTML select elements, or the Web Pages HTML helpers for forms.
The first code sample shows a Razor page that includes a standard HTML select element being populated by the categories extracted from the Northwind database:
@{
    var db = Database.Open("Northwind");
    var categories = db.Query("SELECT CategoryId, CategoryName FROM Categories ORDER BY CategoryName");
}
<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Cascading Dropdown Lists</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    </head>
    <body>
        <div>
            <select id="categoryId" name="categoryId">
                <option value="">-- Select Category --</option>
            @foreach(var category in categories){
                <option value="@category.CategoryId">@category.CategoryName</option>
            }
            </select>
        </div>
        <div>
            <select id="productId">
                <option value="">-- Select Product --</option>
            </select>
        </div>
    </body>
</html>
A second select element is added to the form. This will display products from the chosen category. The next code sample shows the same thing using the Web Pages DropDownList helper instead of HTML elements:
@{
    var db = Database.Open("Northwind");
    var data = db.Query("SELECT CategoryId, CategoryName FROM Categories ORDER BY CategoryName");
    var categories = data.Select(item => new SelectListItem {
        Value = item.CategoryId.ToString(), 
        Text = item.CategoryName
    });
}

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Cascading Dropdown Lists</title>
    </head>
    <body>
        <div>
            @Html.DropDownList("categoryId", "-- Select Category --", categories)
        </div>
        <div>
            @Html.DropDownList("productId", "-- Select Product --", Enumerable.Empty<SelectListItem>())
        </div>
    </body>
</html>
The data is transformed into a collection of SelectListItem objects once it has been obtained from the database. The second (products) dropdown list has an empty collection of SelectListItem objects assigned to it.
When a category has been selected, a filtered list of products needs to be obtained and made available to the second dropdown. Since jQuery is the engine that will be responsible for requesting that data, it makes sense to return it in a format that jQuery is comfortable working with - and that's JSON. Here is the complete GetProducts.cshtml file that is responsible for processing the request and returning the data:
@{
    Layout = null;
    var categoryId = UrlData[0].IsEmpty() ? 1 : UrlData[0].AsInt();  
    var db = Database.Open("Northwind");
    var sql = "SELECT ProductId, ProductName FROM Products WHERE CategoryId = @0 ORDER BY ProductName";
    var products = db.Query(sql, categoryId);
    Json.Write(products, Response.Output);
}
Since you are returning JSON, you must not allow other characters to be included in the response. For that reason, all the default markup has been removed from the file. Layout has been set to null at the top of the file. This acts to override any possibilty that a Layout page has been set in a PageStart file, or might be set in one in the future which would result in extra characters interferring with the generated JSON. In this particular example, I am expecting the CategoryID value to be available in UrlData. If there isn't one, I have decided to use 1 as a default value for demo purposes. Once the data has been extracted from the database, The Json helper is used to convert it into JSON and return it to the requester.
Finally, here is the client-side script that manages the process. It is exactly the same regardless whether you are using HTML elements or HTML helpers:
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.1.min.js" type="text/javascript"></script>
<script>
    $(function () {
        var productsSelect = $('#productId');
        productsSelect.attr('disabled', true);
        $('#categoryId').change(function () {
            var categoryId = $(this).val();
            $.getJSON('/GetProducts/' + categoryId, function (products) {
                productsSelect.attr('disabled', false);
                productsSelect.empty();
                productsSelect.append(
                        $(')
                            .attr('value', '')
                            .text('-- Select Product --'));
                $.each(products, function (index, product) {
                    productsSelect.append(
                        $(')
                            .attr('value', product.ProductId)
                            .text(product.ProductName)
                    );
                });
            });
        });
    });
</script>
You need to include a reference to the jQuery library. I have linked to a CDN-hosted copy of jQuery. The script block initially identifies the dropdown list that the products will appear in, and disables it. Then an event handler is registered that executes when the selected value in the categories dropdown list is changed. The selected value (categoryId) is passed to a getJSON command that requests the GetProducts page. The categoryId value is added to the Url as UrlData. The callback function enables the dropdown list, then clears it of any existing option elements. Then it adds a default option ( -- Select Product -- ) and iterates the products returned in the JSON response and adds those to individual option elements.
download is available which includes a sample site featuring the HTML element approach.

воскресенье, 7 октября 2012 г.

HTTP Redirection in IIS 7 on Windows Server 2008


If you have a website and want to change domain names or if you need to change the architecture of your site, you won’t want visitors following links from other sites and search engines such as Google to get an error while visiting your website. This can cause visitors to click away and a loss of rankings in the search engines.
Luckily there is a fairly simple and straightforward way to remedy the situation through the use of redirects. First, let’s look at the different types of redirects that are available in IIS 7:
  • 301 – Permanent: This redirect tells the Web client that the location of the requested resource has moved permanently
  • 302 – Standard: This redirect tells the Web client to issue a new request to the location specified
  • 307 – Temporary: This redirect tells the Web client to resend POST data, which prevents a Web browser from losing data when the browser issues an HTTP POST request
In most circumstances you will want to use a 301 redirect, as this will inform search engines to update their index with the resource’s new location. In some cases a 302 will be appropriate if the change is going to be short term such as a special page that is seasonal.
For this article I will assume that you already have a site setup on a Windows Server 2008 system setup in a web server role, and are familiar with getting into IIS manager.

Redirect to a Different URL

The first and most simple of the redirects will go from one domain to another, useful if you are changing domain names. I have setup the following two domains TSOriginal.com andTSRedirect.com on my test server as you can see:
IIS 7 Redirection - 1
As you can see, we setup the original domain as TSOriginal.com and have put a simple index.html file in place that looks like this:
IIS 7 Redirection - 2
Now let’s walk through the steps required to setup a redirect to our target domainTSRedirect.com. If it works correctly then we should see the new index.html page below:
IIS 7 Redirection - 3
1. Open IIS Manager by going to Start -> Administrative Tools -> IIS Manager
IIS 7 Redirection - 4
2. Once IIS Manager opens, expand the WebServer, then the Sites folder, and choose the domain, in this case TSOriginal.com.
IIS 7 Redirection - 5
3. Click on HTTP REDIRECT in the main panel
IIS 7 Redirection - 6
4. Place a check next to Redirect requests to this destination: and fill in the target url in the text box below. In this instance it will be TSRedirect.com.
IIS 7 Redirection - 7
5. In the Redirect Behavior we have several decisions to make about how we want the redirects to work. Let’s explore each of these options.
  • Redirect all requests to exact destination – If this object is checked all requests no matter what the original destination will be redirected to the exact location in the text box above. If unchecked everything will be redirected relative to the destination.
  • Only redirect requests to content in this directory (not subdirectories) – By default, when you enable redirection, content can be served by subdirectories below the main directory. If you choose this option you can limit requests to just the directory you want without effecting the subdirectories.
  • Status Code – In this drop down you choose which status code to return when redirecting. As discussed earlier in this article your options are 301302, and 307.
6. For this example we will leave everything unchecked and set a status of 301 in the dropdown menu. Click Apply to set the options.
IIS 7 Redirection - 8
7. The changes are now in place and if we navigate to TSOriginal.com it will redirect us to TSRedirect.com.
To test if the 301 status redirects correctly we will use the live HTTP headers plugin for Firefox. It will allow us to see the status codes. Here are the results for the test:
IIS 7 Redirection - 9
As you can see from the highlighted area the status was returned 301.
All requests now for TSOriginal.com will be sent to TSRedirect.com with a 301 status code relative to the domain name.

Redirect a Single Page to Another Page on the Same Site

This type of redirect is especially useful when you might have some temporary changes to a webpage because of seasonal or holiday changes.
In the case of a seasonal page that will return to normal after a short time, it is best to use a 302redirect. This lets search engines and other sites know that this change is expected and not to change their index or links.
For this example we have removed the site redirect we had placed on TSOriginal.com, and added two pages of content to the site:
oldpage.html
IIS 7 Redirection - 10
newpage.html
IIS 7 Redirection - 11
Now let’s setup a temporary 302 redirect from oldpage.html to newpage.html while.
1. Select the site in IIS manager that you want to set the redirect for.
2. In the Features window switch to Content View, Right click on the page you want to work with, oldpage.htm in this case, and left click on Switch to Features View
IIS 7 Redirection - 12
3. The page now selected in the Connections Pane, click on HTTP Redirect in the features pane
IIS 7 Redirection - 13
4. Check the box next to Redirect requests to this destination, and fill in the destination pagenewpage.htm and set the dropdown menu to 302, and click Apply.
IIS 7 Redirection - 14
5. Now if we navigate to the page TSOriginal.com/oldpage.htm we will be redirected toTSOriginal.com/ newpage.htm.
We will again use the Live HTTP Headers plugin for Firefox to view the redirect. As you can see the pages redirect with the correct 302 status code.
IIS 7 Redirection - 15
You are now ready to do basic redirects in IIS 7 on Windows 2008 server.

суббота, 6 октября 2012 г.

Creating a PHP Web Role in Windows Azure


Earlier this week, I posted an overview of the “new” Windows Azure SDK for PHP. In that post, I promised deeper dives into a few areas of the SDK. In this post I’ll begin delivering on that promise by looking at how to use Windows Azure PowerShell to create and publish a PHP Web Role in Windows Azure. I’ll assume you have created a Windows Azure account.
Note: If you are looking to simply host a PHP website in Windows Azure, you should use Windows Azure Websites. During the free trial period, you can create up to 10 websites and run up to 3 instances of each site at no charge. If your site needs more horsepower, you can move to “reserved” mode (though this mode is not free – see Pricing Details for more information). If, however, you are building an application that requires a customized PHP installation, a multi-tier application, an application that requires advanced administration, or an application that requires advanced networking, then you should consider Windows Azure Web Roles (i.e. Windows Azure’s platform-as-a-service offering). More guidance can be found in this post: Windows Azure Websites, Web Roles, and VMs: When to use which?
The main PowerShell cmdlet for creating a PHP Web Role is the Add-AzurePHPWebRole cmdlet. This cmdlet creates a local directory that is a ready-to-deploy PHP application (though it is very simple – it just displays the output of phpinfo). You simply need to add your code and deploy it. When you deploy the application to Windows Azure, the project will install PHP and configure IIS appropriately using the Web Platform Installer. The version of PHP that gets installed is the latest version of PHP that is available via the Web Platform Installer (which, as of this writing, is PHP 5.3.13). The PHP installation is fully customizable – you can provide your own php.ini file and extension directory to be used by the PHP installation.
Note: The Windows Azure team hopes to make it possible to choose from several PHP versions in the near future. Additionally, the team is working to add support for developing and deploying Web and Worker Roles from non-Windows platforms by adding to the commands available in the Windows Azure Command Line Tools for Mac and Linux.
For a general overview of the cmdlets, see How to use Windows Azure PowerShell.

Get the tools

The easiest way to get the Windows Azure PowerShell cmdlets is to install the Windows Azure SDK for PHP: download the Windows Azure SDK for PHP. That link will download the Web Platform Installer and set you up to install both the PowerShell cmdlets and the Windows Azure Emulators:
install-php-sdk
If you would rather install just the PowerShell cmdlets (and not the Emulators), click the “back” button…
back-button
…and select Windows Azure PowerShell:
just-powershell

Import your publish settings

After you have installed the cmdlets, follow the steps below to import your publish settings. You only need to perform these steps once.
1. Start Windows Azure PowerShell with elevated privileges (from the Start menu, search for Windows Azure PowerShell, right-click and select Run as Administrator).
2. Download your publish settings by executing the command below. This will pull up your web browser and require you to sign in with your Windows Azure account credentials. (Make note of where you save the .publishsettings file.)
Get-AzurePublishSettingsFile
3. Import your publish settings with this command:
Import-PublishSettingsFile

Create a PHP Web Role

After you have imported your publish settings, create a PHP Web Role by following these steps:
1. Create a new Azure project. Note that this command will create a new directory called myAzureProject and automatically change directories to it.
New-AzureServiceProject myAzureProject
2. From the myAzureProject directory (or whatever you called your Azure project), add a PHP Web Role:
Add-AzurePHPWebRole myWebRole
You now have a skeleton PHP/Azure project. Actually, you have a very simple PHP application (displays output of phpinfo) that is ready to deploy. (At this point,you can skip ahead to the Publish to Windows Azure section if you want.)
Inspecting the directory structure, you should see something similar to this:
/myAzureProject
    deploymentSettings.json
    ServiceConfiguration.Cloud.cscfg
    ServiceConfiguration.Local.cscfg
    ServiceDefinition.csdef
        /myWebRole
            index.php
            Web.cloud.config
            Web.config
            /bin
                Microsoft.Web.Deployment.dll
                Microsoft.Web.PlatformInstaller.dll
                Microsoft.Web.PlatformInstaller.UI.dll
                setup.cmd
                setup.ps1
                setup_web.cmd
                WebpiCmdLine.exe
You can now add your application code to the myWebRole folder. If you want to add startup tasks, you can do so by editing the .csdef file and adding scripts to the bin folder. For more information, see How to Define Startup Tasks for a Role.

Customize your PHP configuration

As I mentioned earlier, the Add-AzurePHPWebRole cmdlet creates a scaffold project that, when deployed, will install the latest version of PHP available via the Web Platform Installer. As of this writing, PHP 5.3.13 is the available version, and it comes with the standard, “out-of the-box” configuration. However, you can customize this configuration by doing the following (skip step 2 if you don’t want to enable any custom extensions):
1. Add a php folder to the bin directory.
2. Add a ext folder to the php directory and put any PHP extensions you want to be available in the folder (e.g.php_mongo.dll).
3. Add a custom php.ini file to the php directory. You can turn settings on/off and enable extensions as you would with any other PHP installation via this .ini file.

Test in the Compute Emulator

If you installed the Windows Azure Emulators, you can test your application locally by executing the following command from the project directory:
Start-AzureEmulator
However, to will need to have PHP installed to do this, as the emulator uses your local PHP installation. More specifically, it will use the PHP version that is in your PATH environment variable, or it will use any version of PHP that was installed using the Web Platform Installer. (Look for a more detailed post soon about how to use the emulators.)

Enable Remote Desktop access

This is a completely optional step, but I have found that enabling remote desktop access has been very helpful in troubleshooting. And, this one cmdlet makes it easy:
Enable-AzureServiceProjectRemoteDesktop
You will be prompted to provide a user name and password that you will use when accessing an instance. After you have deployed the project (details in the section below), you can access an instance by logging into the management portal, clicking INSTANCES on your website’s dashboard, selecting an instance, and clicking CONNECT at the bottom of the page.
connect
If you are using the production portal, navigate to an instance and click the connect icon:
old-portal

Publish to Windows Azure

Finally, you can publish your project to Windows Azure with the following command:
Publish-AzureServiceProject
This will attempt to create a cloud service using your project name (myAzureProject in the examples above). If that name is not available, you may get an error. If that happens you can deploy it with a different name by using the –ServiceName flag:
Publish-AzureServiceProject –ServiceName myNewServiceName
You can check to see if a name is available with this command:
Test-AzureName –Service “myAzureProject”
Additional flags for the Publish-AzureServiceProject cmdlet are –Slot, –Location, –Subscription, and –Storage. For more information on using these flags, see How to use Windows Azure PowerShell.
After you deploy a project, it will take several minutes before it is available as Windows Azure provisions and configures new virtual machines for each deployment.
That’s it for now. As usual, let us know if you have any feedback.
Thanks.

Windows Azure Web Sites vs Web Roles


One of the things that I have been pondering since the Windows Azure announcements is when you would use Web Sites over Web Roles. I’ve done a few Google’s over the last few days to see if anyone was blogging about it apart from the initial post by Scott Gu, but hadn’t found anything until a Stack Overflow post came up this morning and since then acouple of posts by Nathan Totten (creator of Accelerator for Web Roles, which has been deprecated by Azure Web Sites, and who works on Azure for Microsoft).
This, in combination with the thinking that I have already been doing and actually having a play with Web Sites has enabled me to come up with the following post. As a warning, some of this will probably change over the next few weeks and months since Web Sites is a brand new product that Microsoft are still probably actively developing. Also, I’ve tried to back up everything I’ve said with URLs, screen shots or just trying it out, but it’s possible I’ve got one or two things wrong since there isn’t much material out there on it yet.

Web Sites

Long-story short: Convention over configuration (without much flexibility to configure on top of that relative to Web Roles) style platform to get you up and running quickly in Azure (kinda like App Harbor). Also, allows you to use a certain amount of Azure resources for free (10 websites on shared instances with limited bandwidth), which is a welcome addition and will be great for proof of concepts or just playing around with stuff!
The main advantages that Web Sites seems to have over Web Roles are:
  • Out of the box support for GitTFSFTP and Web Deploy deployments, which makes automated deployments and continuous delivery easier (not that it’s terribly difficult using PowerShell for Web Roles).
    • Annoyingly (unless I’ve missed something), the git publishing doesn’t use private keys so you have to keep typing in the password, although from watching David Ebbo’s Youtube video on publishing from Git there must be some way to make it remember the password (I wouldn’t know as I always use private keys). [See update at end of post for instructions]
    • It would be cool if some of these features were added to Web Roles and Worker Roles; I’m not sure if this tweet from David Ebbo is any indication that might happen!
    • It seems that Microsoft have open sourced their Git-IIS deployment library, Kudu, which is cool :)
    • I tried to deploy a solution that had multiple web projects, but no matter what I did it kept deploying the first web project that I had deployed. I’m not sure what conventions it uses, but if you need to configure which project is deployed then I imagine you can consult the relevant Kudu documentation.
    • If you use the Git publishing model (and I assume the TFS publishing model) then you don’t have to commit your NuGet package binaries as they will automatically get resolved when you push (you do have to turn on Package Restore on the solution in Visual Studio for it to do it though). This is great because it makes your deployment much faster. It does mean that if you use packages that aren’t in the official NuGet repository (e.g. in a private repository, or using a package service) then you will need to include those ones – I haven’t tried seeing what happens when you do that though yet, so try with caution.
  • Gives you the ability to roll-back to previous deployments instantly via the management portal if you are using Git (and I assume TFS) deployments.
    Redeploy previous deployments
  • You can deploy almost instantly out of the box (with the above mentioned deployment methods), rather than in 8+ minutes or having to set up something like Accelerator for Web Roles.
  • You can provision a new Web Site much faster than a Web Role (seconds rather than 15+ minutes); I’m guessing Microsoft will always have spare capacity spun up and ready at any point in time – their capacity management software must be fascinating!
  • For .NET web apps: You don’t have to set up a separate project in your Visual Studio solution to deploy to Azure – you can simply deploy a normal web app solution as-is.
    • This also means you don’t have to maintain two sets of configurations and set up a storage account for diagnostics so you can be up and running much quicker.
  • Out of the box support for installing a CMS (from a list of common CMS’s and blogs).Create Azure Web Site with CMS
  • The regions that you can deploy too are currently restricted while this feature is in preview, but there are probably plans to roll out wider (see point 3 in the link).Azure Web Sites regions
  • Built-in, web site relevant monitoring from the management portal (Web Roles has CPU and (optionally) memory as well now, but this also includes HTTP errors, requests and data):
    Monitoring dashboard
  • Ability to inject configuration variables to your web.config file rather than having to package the final version with the deployment.
    • This means you don’t have to use encrypted web.config files if you want to keep production configuration information in source control so you can do automated deployments, but still prevent developers from accessing the production environment.
    • It does mean you potentially need to be more careful about who you give access to the management portal for your instances because the connection strings will appear in plain text.
  • If you have a web.release.config file then the XDT transformations in this file will automatically be applied before deploying your site.
  • You can add multiple host names that your site responds to (if it’s using reserved instances, but not for shared free mode).
    • It appears you have to do this if you want to point a CName record at the site – given there are multiple sites being hosted on the same IIS instances this makes sense.
    • Given Web Roles allow you to point as many domain names as you want at it and it will resolve for all of them (assuming you are trying to resolve the main web site that is deployed in the Azure package rather than using a solution like Accelerator for Web Roles, which does require you to specify the host name) this isn’t really an advantage that Web Sites has over Web Roles.
    • What it does mean though is that you can host multiple sites on a single set of reserved servers out of the box (which is why Web Sites deprecates Accelerator for Web Roles in combination with near-instant deployments).
    • There is an implication if you are using shared free hosting rather than reserved that you can’t point custom domain names to your web site and thus have to use the azurewebsites.net domain name (which is probably fine if you are doing a prototype or proof of concept).
    • It seems that for a given subscription in a given region you can have either sharedor reserved Web Sites and thus any web sites that you add for a given subscription / region that has reserved Web Sites will be shared on your reserved servers.
      • I can’t confirm this explicitly, but it’s the only thing that makes sense to me after seeing the management portal and reading between the lines in the documentation.Web Site ModeShared to ReservedReserved to Shared
      • I would suggest that it will be important to keep this in mind if you want to segregate the servers that certain combinations of web sites that you deploy. You might want to do this due to their load profiles conflicting with each other. This is important unless Microsoft provides an easy way in the future to segregate your reserved instances within a single subscription or provide an easy way to migrate a site to a different subscription or region (unless I am missing something!).
  • You can use MySQL.
  • It takes seconds rather than minutes to scale out more instances.
  • You can’t join it to a Virtual Network
  • You can host your “naked” domain name (i.e. without www.) in a supported way rather than having to resort to external servicesclever programmatic solutions or being careful not to nuke your deployment

Web Roles

With all that in mind, this is what I see as the advantages of / situations you would use Web Roles:
  • If you need to create an application that has non standard HTTP ports open (or frankly ports open for any other reason) you have to use Web Roles.
  • If you want to be able to RDP into the server for debugging or other purposes you have to use Web Roles (or VM Roles).
  • If you want surety about network / virtual machine isolation of your application for security reasons you may not want to use (at the very least shared) Web Sites. This is a bit of conjecture though because without knowing the internals of how Web Sites is implemented it’s hard to say what kind of isolation it provides.
  • If you want to deploy a worker role to perform background processing alongside your web site via a worker role then you can do it using the same instance with a Web Role (thus costing less money).
  • You can run elevated start up scripts with a Web Role that then allow you to install any software you want or configure it in any way you desire.
  • You have full control over what diagnostic information is collected from a Web Role, which you may want to use for auto scaling, or customised monitoring solutions.
  • You have full control over how IIS is configured in a Web Role.
  • Your Web Role endpoint resolves to a static IP address assuming you don’t nuke your deployment. I assume the same thing applies for reserved mode Web Sites, but I haven’t confirmed.
  • You can automatically scale your web site using Web Roles.
  • You can scale out to a very large number of instances for extremely high load web sites (I know of a situation where at least 250 instances were used). Web Sites (at least at the moment, and with the default configuration when you first get it – it’s potentially possible to increase this) seems to have a maximum of three instances.Capacity
  • Furthermore, as per above screen shot and at least for the moment, Web Sites doesn’t have Extra Small (great for cost effective hosting of low load web sites – but the free shared instances makes up for this) or Extra Large (if you need extreme vertical scale – but you probably only need this for intense Worker Role processing rather than for web sites).
  • At the moment you can only have SSL connections to your custom domain name by using Web Roles since there is no ability to upload Security Certificates to your Web Site instances, but this will probably be added soon. There is SSL for the azurewebsites.net domain name that you get though.
  • If you want Security Certificates for any other purpose e.g. config encryption, authentication, etc. then you will need to use Web Roles (for now at least).
  • Apparently, during the preview there is a limit of 1GB of space per subscription that can be used with Web Sites and you can have a maximum of 10 web sites. I found this in a Stack Overflow answer from a Microsoft employee working on Azure. Free and paid shared instances have a limit of 1GB of space with free instances having a limit of 10 web sites (reserved instances have 10GB of space). With Accelerator for Web Roles there is no limit on the number of sites, and depending on your role size you can certainly have more than 1 GB of storage (apart from the fact you have have more than one hosted service, each with more than 1 GB of space).
  • If you want to have any domain name you want to resolve against your web site using a CName without having to specify those domain names explicitly in the management portal then you will need to use Web Roles (see the comments section below for explanation).
While reading up on this post I found out something about Web Roles that I didn’t know – apparently you can deploy a Web Role package that contains multiple web sites (by specifying their host headers).
I should note that at this stage I haven’t looked at the improvements that Microsoft have added to the .NET SDK, although I would say it’s unlikely any of them will affect the difference between Web Roles and Web Sites.

Conclusion

If you need enormous scale, SSL, Asian or West US data centres, a non-standard configuration (of IIS, ports, diagnostics, security certs or start up scripts), RDP or cost-effective Worker Roles (combined with your Web Role) then you are going to have to stick to Web Roles for now. Otherwise, what are you waiting for – sign up for Web Sites because it’s pretty amazing :) !

Accelerator for Web Roles

Unfortunately, the above list excludes me from using Web Sites for now because we deploy to South East Asia (lowest latency to Australia), need SSL and also need extra Security Certs for some of our apps. Also, for at least a couple of applications we need the surety on network and VM isolation that Web Roles has.
Given that a 8+ minute deployment for a web site is unacceptable for me that means I’m going to have to keep with Accelerator for Web Roles for now even though it’s deprecated. In some ways it’s a shame because I have had a couple of problems with it so I’m probably going to have to put some work into it before we use it for the really important web site my team is currently developing.
At this stage it’s unclear whether it’s Microsoft’s intention to migrate all the Web Role features to Web Sites and in time replace Web Roles completely – that would be totally excellent! We will have to wait and see… Exciting times!

Update (10 June 2012)

David Ebbo send me a message via Twitter to let me know the solution he is using to remember his Git password. Also, I found a post that describes how to point to other NuGet feeds than the official one when using package restore.

Update (28 August 2012)

I read a truly excellent post yesterday about Virtual Networks and it made the point that you can’t join a Web Site to a Virtual Network, but of course you can join a VM or Web/Worker Role. Thus I added that as another limitation above.

Update (15 September 2012)

Update (18 September 2012)

There were a few big announcements today about Azure Web Sites and I’ve updated this post with some minor corrections accordingly.