Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Hybrid Azure applications using OData

    OData in the cloud on AzureIn the whole Windows Azure story, Microsoft has always been telling you could build hybrid applications: an on-premise application with a service on Azure or a database on SQL Azure. But how to do it in the opposite direction? Easy answer there: use the (careful, long product name coming!) Windows Azure platform AppFabric Service Bus to expose an on-premise WCF service securely to an application hosted on Windows Azure. Now how would you go about exposing your database to Windows Azure? Open a hole in the firewall? Use something like PortBridge to redirect TCP traffic over the service bus? Why not just create an OData service for our database and expose that over AppFabric Service Bus. In this post, I’ll show you how.

    For those who can not wait: download the sample code: ServiceBusHost.zip (7.87 kb)

    kick it on DotNetKicks.com

    What we are trying to achieve

    The objective is quite easy: we want to expose our database to an application on Windows Azure (or another cloud or in another datacenter) without having to open up our firewall. To do so, we’ll be using an OData service which we’ll expose through Windows Azure platform AppFabric Service Bus. But first things first…

    • OData??? The Open Data Protocol (OData) is a Web protocol for querying and updating data over HTTP using REST. And data can be a broad subject: a database, a filesystem, customer information from SAP, … The idea is to have one protocol for different datasources, accessible through web standards. More info? Here you go.
    • Service Bus??? There’s an easy explanation to this one, although the product itself offers much more use cases. We’ll be using the Service Bus to interconnect two applications, sitting on different networks and protected by firewalls. This can be done by using the Service Bus as the “man in the middle”, passing around data from both applications.

    Windows Azure platform AppFabric Service Bus

    Our OData feed will be created using WCF Data Services, formerly known as ADO.NET Data Services formerly known as project Astoria.

    Creating an OData service

    We’ll go a little bit off the standard path to achieve this, although the concepts are the same. Usually, you’ll be adding an OData service to a web application in Visual Studio. Difference: we’ll be creating a console application. So start off with a console application and add the following additional references to the console application:

    • Microsoft.ServiceBus (from the SDK that can be found on the product site)
    • System.Data.Entity
    • System.Data.Services
    • System.Data.Services.Client
    • System.EnterpriseServices
    • System.Runtime.Serialization
    • System.ServiceModel
    • System.ServiceModel.Web
    • System.Web.ApplicationServices
    • System.Web.DynamicData
    • System.Web.Entity
    • System.Web.Services
    • System.Data.DataSetExtensions

    Next, add an Entity Data Model for a database you want to expose. I have a light version of the Contoso sample database and will be using that one. Also, I only added one table to the model for sake of simplicity:

    Entity Data Model for OData

    Pretty straightforward, right? Next thing: expose this beauty through an OData service created with WCF Data Services. Add a new class to the project, and add the following source code:

    1 public class ContosoService : DataService<ContosoSalesEntities> 2 { 3 // This method is called only once to initialize service-wide policies. 4 public static void InitializeService(DataServiceConfiguration config) 5 { 6 // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. 7 // Examples: 8 // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); 9 // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); 10 config.SetEntitySetAccessRule("Store", EntitySetRights.All); 11 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; 12 } 13 }

    Let’s explain this thing: the ContosoService class inherits DataService<ContosoSalesEntities>, a ready-to-use service implementation which you pass the type of your Entity Data Model. In the InitializeService method, there’s only one thing left to do: specify the access rules for entities. I chose to expose the entity set “Store” with all rights (read/write).

    In a normal world: this would be it: we would now have a service ready to expose our database through OData. Quick, simple, flexible. But in our console application, there’s a small problem: we are not hosting inside a web application, so we’ll have to write the WCF hosting code ourselves.

    Hosting the OData service using a custom WCF host

    Since we’re not hosting inside a web application but in a console application, there’s some plumbing we need to do: set up our own WCF host and configure it accordingly.

    Let’s first work on our App.config file:

    1 <?xml version="1.0"?> 2 <configuration> 3 <connectionStrings> 4 <add name="ContosoSalesEntities" connectionString="metadata=res://*/ContosoModel.csdl|res://*/ContosoModel.ssdl|res://*/ContosoModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\SQLEXPRESS;Initial Catalog=ContosoSales;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient"/> 5 </connectionStrings> 6 7 <system.serviceModel> 8 <services> 9 <service behaviorConfiguration="contosoServiceBehavior" 10 name="ServiceBusHost.ContosoService"> 11 <host> 12 <baseAddresses> 13 <add baseAddress="http://localhost:8080/ContosoModel" /> 14 </baseAddresses> 15 </host> 16 <endpoint address="" 17 binding="webHttpBinding" 18 contract="System.Data.Services.IRequestHandler" /> 19 20 <endpoint address="https://<service_namespace>.servicebus.windows.net/ContosoModel/" 21 binding="webHttpRelayBinding" 22 bindingConfiguration="contosoServiceConfiguration" 23 contract="System.Data.Services.IRequestHandler" 24 behaviorConfiguration="serviceBusCredentialBehavior" /> 25 </service> 26 </services> 27 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 28 29 <behaviors> 30 <serviceBehaviors> 31 <behavior name="contosoServiceBehavior"> 32 <serviceMetadata httpGetEnabled="true" /> 33 <serviceDebug includeExceptionDetailInFaults="True" /> 34 </behavior> 35 </serviceBehaviors> 36 37 <endpointBehaviors> 38 <behavior name="serviceBusCredentialBehavior"> 39 <transportClientEndpointBehavior credentialType="SharedSecret"> 40 <clientCredentials> 41 <sharedSecret issuerName="owner" issuerSecret="<secret_from_portal>" /> 42 </clientCredentials> 43 </transportClientEndpointBehavior> 44 </behavior> 45 </endpointBehaviors> 46 </behaviors> 47 48 <bindings> 49 <webHttpRelayBinding> 50 <binding name="contosoServiceConfiguration"> 51 <security relayClientAuthenticationType="None" /> 52 </binding> 53 </webHttpRelayBinding> 54 </bindings> 55 </system.serviceModel> 56 </configuration>

    There's a lot of stuff going on in there!

    • The connection string to my on-premise database is specified
    • The WCF service is configured

    To be honest: that second bullet is a bunch of work…

    • We specify 2 endpoints: one local (so we can access the OData service from our local network) and one on the service bus, hence the https://<service_namespace>.servicebus.windows.net/ContosoModel/ URL.
    • The service bus endpoint has 2 behaviors specified: the service behavior is configured to allow metadata retrieval. The endpoint behavior is configured to use the service bus credentials (that can be found on the AppFabric portal site once logged in) when connecting to the service bus.
    • The webHttpRelayBinding, a new binding type for Windows Azure AppFabric Service Bus, is configured to use no authentication when someone connects to it. That way, we will have an OData service that is accessible from the Internet for anyone.

    With that configuration in place, we can start building our WCF service host in code. Here’s the full blown snippet:

    1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect; 6 7 using (ServiceHost serviceHost = new WebServiceHost(typeof(ContosoService))) 8 { 9 try 10 { 11 // Open the ServiceHost to start listening for messages. 12 serviceHost.Open(TimeSpan.FromSeconds(30)); 13 14 // The service can now be accessed. 15 Console.WriteLine("The service is ready."); 16 foreach (var endpoint in serviceHost.Description.Endpoints) 17 { 18 Console.WriteLine(" - " + endpoint.Address.Uri); 19 } 20 Console.WriteLine("Press <ENTER> to terminate service."); 21 Console.ReadLine(); 22 23 // Close the ServiceHost. 24 serviceHost.Close(); 25 } 26 catch (TimeoutException timeProblem) 27 { 28 Console.WriteLine(timeProblem.Message); 29 Console.ReadLine(); 30 } 31 catch (CommunicationException commProblem) 32 { 33 Console.WriteLine(commProblem.Message); 34 Console.ReadLine(); 35 } 36 } 37 } 38 }

    We’ve just created our hosting environment, completely configured using the configuration file for WCF. The important thing to note here is that we’re spinning up a WebServiceHost, and that we’re using it to host multiple endpoints. Compile, run, F5, and here’s what happens:

    Command line WCF hosting for AppFabric service bus

    Consuming the feed

    Now just leave that host running and browse to the public service bus endpoint for your OData service, i.e. https://<service_namespace>.servicebus.windows.net/ContosoModel/:

    Consuming OData over service bus

    There’s two reactions possible now: “So, this is a service?” and “WOW! I actually connected to my local SQL Server database using a public URL and I did not have to call IT to open up the firewall!”. I’d go for the latter…

    Of course, you can also consume the feed from code. Open up a new project in Visual Studio, and add a service reference for the public service bus address:

    Add reference OData

    The only thing left now is consuming it, for example using this code snippet:

    1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var odataService = 6 new ContosoSalesEntities( 7 new Uri("https://<service_namespace>.servicebus.windows.net/ContosoModel/")); 8 var store = odataService.Store.Take(1).ToList().First(); 9 10 Console.WriteLine("Store: " + store.StoreName); 11 Console.ReadLine(); 12 } 13 }

    (Do not that updates do not work out-of-the-box, you’ll have to use a small portion of magic on the server side to fix that… I’ll try to follow up on that one.)

    Conclusion

    That was quite easy! Of course, if you need full access to your database, you are currently stuck with PortBridge or similar solutions. I am not completely exposing my database to the outside world: there’s an extra level of control in the EDMX model where I can choose which datasets to expose and which not. The WCF Data Services class I created allows for specifying user access rights per dataset.

    Download sample code: ServiceBusHost.zip (7.87 kb)

    kick it on DotNetKicks.com


    Categories: Azure | C# | General

    Simplified access control using Windows Azure AppFabric Labs

    Windows Azure ApFabric Access ControlEarlier this week, Zane Adam announced the availability of the New AppFabric Access Control service in LABS. The highlights for this release (and I quote):

    • Expanded Identity provider support - allowing developers to build applications and services that accept both enterprise identities (through integration with Active Directory Federation Services 2.0), and a broad range of web identities (through support of Windows Live ID, Open ID, Google, Yahoo, Facebook identities) using a single code base.
    • WS-Trust and WS-Federation protocol support – Interoperable WS-* support is important to many of our enterprise customers.
    • Full integration with Windows Identity Foundation (WIF) - developers can apply the familiar WIF identity programming model and tooling for cloud applications and services.
    • A new management web portal -  gives simple, complete control over all Access Control settings.

    Wow! This just *has* to be good! Let’s see how easy it is to work with claims based authentication and the AppFabric Labs Access Control Service, which I’ll abbreviate to “ACS” throughout this post.

    kick it on DotNetKicks.com

    What are you doing?

    In essence, I’ll be “outsourcing” the access control part of my application to the ACS. When a user comes to the application, he will be asked to present certain “claims”, for example a claim that tells what the user’s role is. Of course, the application will only trust claims that have been signed by a trusted party, which in this case will be the ACS.

    Fun thing is: my application only has to know about the ACS. As an administrator, I can then tell the ACS to trust claims provided by Windows Live ID or Google Accounts, which will be reflected to my application automatically: users will be able to authenticate through any service I configure in the ACS, without my application having to know. Very flexible, as I can tell the ACS to trust for example my company’s Active Directory and perhaps also the Active Directory of a customer who uses the application

    Prerequisites

    Before you start, make sure you have the latest version of Windows Identity Foundation installed. This will make things easy, I promise! Other prerequisites, of course, are Visual Studio and an account on https://portal.appfabriclabs.com. Note that, since it’s still a “preview” version, this is free to use.

    In the labs account, create a project and in that project create a service namespace. This is what you should be seeing (or at least: something similar):

    AppFabric labs project

    Getting started: setting up the application side

    Before starting, we will require a certificate for signing tokens and things like that. Let’s just start with creating one so we don’t have to worry about that further down the road. Issue the following command in a Visual Studio command prompt:

    MakeCert.exe -r -pe -n "CN=<your service namespace>.accesscontrol.appfabriclabs.com" -sky exchange -ss my

    This will create a certificate that is valid for your ACS project. It will be installed in the local certificate store on your computer. Make sure to export both the public and private key (.cer and .pkx).

    That being said and done: let’s add claims-based authentication to a new ASP.NET Website. Simply fire up Visual Studio, create a new ASP.NET application. I called it “MyExternalApp” but in fact the name is all up to you. Next, edit the Default.aspx page and paste in the following code:

    1 <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" 2 CodeBehind="Default.aspx.cs" Inherits="MyExternalApp._Default" %> 3 4 <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> 5 </asp:Content> 6 <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> 7 <p>Your claims:</p> 8 <asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False"> 9 <Columns> 10 <asp:BoundField DataField="ClaimType" HeaderText="ClaimType" ReadOnly="True" /> 11 <asp:BoundField DataField="Value" HeaderText="Value" ReadOnly="True" /> 12 </Columns> 13 </asp:GridView> 14 </asp:Content>

    Next, edit Default.aspx.cs and add the following Page_Load event handler:

    1 protected void Page_Load(object sender, EventArgs e) 2 { 3 IClaimsIdentity claimsIdentity = 4 ((IClaimsPrincipal)(Thread.CurrentPrincipal)).Identities.FirstOrDefault(); 5 6 if (claimsIdentity != null) 7 { 8 gridView.DataSource = claimsIdentity.Claims; 9 gridView.DataBind(); 10 } 11 }

    So far, so good. If we had everything configured, Default.aspx would simply show us the claims we received from ACS once we have everything running. Now in order to configure the application to use the ACS, there’s two steps left to do:

    • Add a reference to Microsoft.IdentityModel (located somewhere at C:\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5\Microsoft.IdentityModel.dll)
    • Add an STS reference…

    That first step should be easy: add a reference to Microsoft.IdentityModel in your ASP.NET application. The second step is almost equally easy: right-click the project and select “Add STS reference…”, like so:

    Add STS reference

    A wizard will pop-up. Here’s a secret: this wizard will do a lot for us! On the first screen, enter the full URL to your application. I have mine hosted on IIS and enabled SSL, hence the following screenshot:

    Specify application URI

    In the next step, enter the URL to the STS federation metadata. To the what where? Well, to the metadata provided by ACS. This metadata contains the types of claims offered, the certificates used for signing, … The URL to enter will be something like https://<your service namespace>.accesscontrol.appfabriclabs.com:443/FederationMetadata/2007-06/FederationMetadata.xml:

    Security Token Service

    In the next step, select “Disable security chain validation”. Because we are using self-signed certificates, selecting the second option would lead us to doom because all infrastructure would require a certificate provided by a valid certificate authority.

    From now on, it’s just “Next”, “Next”, “Finish”. If you now have a look at your Web.config file, you’ll see that the wizard has configured the application to use ACS as the federation authentication provider. Furthermore, a new folder called “FederationMetadata” has been created, which contains an XML file that specifies which claims this application requires. Oh, and some other details on the application, but nothing to worry about at this point.

    Our application has now been configured: off to the ACS side!

    Getting started: setting up the ACS side

    First of all, we need to register our application with the Windows Azure AppFabric ACS. his can be done by clicking “Manage” on the management portal over at https://portal.appfabriclabs.com. Next, click “Relying Party Applications” and “Add Relying Party Application”. The following screen will be presented:

    Add Relying Party Application

    Fill out the form as follows:

    • Name: a descriptive name for your application.
    • Realm: the URI that the issued token will be valid for. This can be a complete domain (i.e. www.example.com) or the full path to your application. For now, enter the full URL to your application, which will be something like https://localhost/MyApp.
    • Return URL: where to return after successful sign-in
    • Token format: we’ll be using the defaults in WIF, so go for SAML 2.0.
    • For the token encryption certificate, select X.509 certificate and upload the certificate file (.cer) we’ve been using before
    • Rule groups: pick one, best is to create a new one specific to the application we are registering

    Afterwards click “Save”. Your application is now registered with ACS.

    The next step is to select the Identity Providers we want to use. I selected Windows Live ID and Google Accounts as shown in the next screenshot:

    Identity Providers

    One thing left: since we are using Windows Identity Foundation, we have to upload a token signing certificate to the portal. Export the private key of the previously created certificate and upload that to the “Certificates and Keys” part of the management portal. Make sure to specify that the certificate is to be used for token signing.

    Signing certificate Windows Identity Foundation WIF

    Allright, we’re almost done. Well, in fact: we are done! An optional next step would be to edit the rule group we’ve created before. This rule group will describe the claims that will be presented to the application asking for the user’s claims. Which is very powerful, because it also supports so-called claim transformations: if an identity provider provides ACS with a claim that says “the user is part of a group named Administrators”, the rules can then transform the claim into a new claim stating “the user has administrative rights”.

    Testing our setup

    With all this information and configuration in place, press F5 inside Visual Studio and behold… Your application now redirects to the STS in the form of ACS’ login page.

    Sign in using AppFabric

    So far so good. Now sign in using one of the identity providers listed. After a successful sign-in, you will be redirected back to ACS, which will in turn redirect you back to your application. And then: misery :-)

    Request validation

    ASP.NET request validation kicked in since it detected unusual headers. Let’s fix that. Two possible approaches:

    • Disable request validation, but I’d prefer not to do that
    • Create a custom RequestValidator

    Let’s go with the latter option… Here’s a class that you can copy-paste in your application:

    1 public class WifRequestValidator : RequestValidator 2 { 3 protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) 4 { 5 validationFailureIndex = 0; 6 7 if (requestValidationSource == RequestValidationSource.Form && collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal)) 8 { 9 SignInResponseMessage message = WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage; 10 11 if (message != null) 12 { 13 return true; 14 } 15 } 16 17 return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex); 18 } 19 }

    Basically, it’s just validating the request and returning true to ASP.NET request validation if a SignInMesage is in the request. One thing left to do: register this provider with ASP.NET. Add the following line of code in the <system.web> section of Web.config:

    <httpRuntime requestValidationType="MyExternalApp.Modules.WifRequestValidator" />

    If you now try loading the application again, chances are you will actually see claims provided by ACS:

    Claims output from Windows Azure AppFabric Access Control Service

    There', that’s it. We now have successfully delegated access control to ACS. Obviously the next step would be to specify which claims are required for specific actions in your application, provide the necessary claims transformations in ACS, … All of that can easily be found on Google Bing.

    Conclusion

    To be honest: I’ve always found claims-based authentication and Windows Azure AppFabric Access Control a good match in theory, but an ugly and cumbersome beast to work with. With this labs release, things get interesting and almost self-explaining, allowing for easier implementation of it in your own application. As an extra bonus to this blog post, I also decided to link my ADFS server to ACS: it took me literally 5 minutes to do so and works like a charm!

    Final conclusion: AppFabric team, please ship this soon :-) I really like the way this labs release works and I think many users who find the step up to using ACS today may as well take the step if they can use ACS in the easy manner the labs release provides.

    By the way: more information can be found on http://acs.codeplex.com.

    kick it on DotNetKicks.com


    Categories: Azure | C# | General | Security

    Manage your SQL Azure database from your browser

    Yesterday, I noticed on Twitter that the SQL Azure - Project “Houston” CTP 1 has been released online. For those who do not know Houston, this is a lightweight and easy to use database management tool for SQL Azure databases built in Silverlight. Translation: you can now easily manage your SQL Azure database using any browser. It’s not a replacement for SSMS, but it’s a viable, quick solution into connecting to your cloudy database.

    kick it on DotNetKicks.com

    A quick look around

    After connecting to your SQL Azure database through http://manage.sqlazurelabs.com, you’ll see a quick overview of your database elements (tables, views, stored procedures) as well as a fancy, three-dimensional cube displaying your database details.

    image

    Let’s create a new table… After clicking the “New table” toolbar item on top, a simple table designer pops up:

    image

    You can now easily design a table (in a limited fashion), click the “Save” button and go enter some data:

    image

    Stored procedures? Those are also supported:

    image

    Even running stored procedures:

    image

    Conclusion

    As you can probably see from the screenshots, project “Houston” is currently quite limited. Basic operations are supported, but for example dropping a table should be done using a custom, hand-crafted query instead of a simple box.

    What I would love to see is that the tool gets a bit more of the basic database operations and a Windows Phone 7 port? That would allow me to quickly do some trivial SQL Azure tasks both from my browser as well as from my (future :-)) smartphone.


    Categories: Azure | General | SQL Azure

    Running on Windows Azure - ChronoRace - Autoscaling

    image At RealDolmen, we had the luck of doing the first (known) project on Windows Azure in Belgium. Together with Microsoft, we had the opportunity to make the ChronoRace website robust enough to withstand large sports events like the 20km through Brussels.

    ChronoRace is a Belgian company based in Malmédy, specialised in electronic timing for large sports events (around 340 per year) troughout Europe in different disciplines like jogging, cycling, sailing, … Each participant is registered through the website, can consult their results and can view a high-definition video of their arrival at the finish line. Of course, these results and videos are also used to brag to co-workers and family members, resulting in about 10 result and video views per participant. Imagine 20.000 or more participants on large events… No wonder their current 1 webserver – 1 database server setup could not handle all load.

    Extra investments in hardware, WAN connection upgrades and video streaming were considered, however found too expensive to have these running for 365 days a year while on average this extra capacity would only be needed for 14 days a year. Ideal for cloud computing! Especially with an expected 30.000 participants for the 20km through Brussels... (which would mean 3 TB of data transfers for the videos on 1 day!!!)

    Microsoft selected RealDolmen as a partner for this project, mainly because of the knowledge we built over the past year, since the first Azure CTP. Together with ChronoRace, we gradually moved the existing SQL Server databse to SQL Azure. After that, we started moving the video streaming to blob storage, implemented extra caching and automatic scaling.

    You probably have seen the following slides in various presentations on cloud computing:

    Capacity cloud computing

    All marketing gibberish, right? Nope! We actually managed to get very close to this model using our custom autoscaling mechanism. Here are some figures we collected during the peak of the 20km through Brussels:

    Windows Azure Auto Scaling

    More information on the technical challenges we encountered can be found in my slide deck I presented at KAHOSL last week:

    If you want more information on scalability and automatic scaling, feel free to come to the Belgian Community Day 2010 where I will be presenting a session on this topic.

    Oh and for the record: I’m not planning on writing marketing posts. I just was so impressed by our actual autoscaling graph that I had to blog this :-)


    Taking Care of a Cloud Environment (slides)

    It looks like I’m only doing sessions lately :-) Here’s another slide deck for a presentation I did on the Architect Forum last week in Belgium.

    Abstract: “No, this session is not about greener IT. Learn about using the RoleEnvironment and diagnostics provided by Windows Azure. Communication between roles, logging and automatic upscaling of your application are just some of the possibilities of what you can do if you know about how the Windows Azure environment works.”

    Thanks for attending!


    Linuxwochen Austria

    As part of my global domination plans, I this week visited Vienna, Austria for a session at Linuxwochen around PHP on Windows.

    PHP on Windows

    Abstract: “Ever wanted to get started with PHP development on Windows? This session covers the basics of running PHP on the Windows platform and will help getting your development environment ready.”

    Thanks for being in this session! I know it is a controversial one on a Linux event :-)


    TechDays 2010 Portugal slides and demo code

    First of all: thank you for attending the sessions Kevin Dockx and I gave at TechDays 2010 Portugal! A wonder we made it there with all the ash clouds and volcanic interference based in Iceland.

    Just Another Wordpress Weblog, But More Cloudy

    Abstract: “While working together with Microsoft on the Windows Azure SDK for PHP, we found that we needed an popular example application hosted on Microsoft’s Windows Azure. Wordpress was an obvious choice, but not an obvious task. Learn more about Windows Azure, the PHP SDK that we developed, SQL Azure and about the problems we faced porting an existing PHP application to Windows Azure.”

    I can not disclose demo code at this time, sorry. Here’s a list of good resources to get you started though:

    PHP and Silverlight

    Abstract: “So you have an existing PHP application and would like to spice it up with a rich and attractive front-end. Next to Adobe Flex, you can also choose Silverlight as a solution. This session shows you around in Silverlight and shows that PHP and Silverlight can go together easily.”

    Demo code: PHP and Silverlight - DevDays.zip (1.00 mb) (based on Silverlight 2, bug Kevin for a recent version :-))


    Using Windows Azure Drive in PHP (or Ruby)

    At the JumpIn Camp in Zürich this week, we are trying to get some of the more popular PHP applications running on Windows Azure. As you may know, Windows Azure has different storage options like blobs, tables, queues and drives. There’s the Windows Azure SDK for PHP for most of this, except for drives. Which is normal: drives are at the operating system level and have nothing to do with the REST calls that are used for the other storage types. By the way: I did a post on using Windows Azure Drive (or “XDrive”) a while ago if you want more info.

    Unfortunately, .NET code is currently the only way to create and mount these virtual hard drives from Windows Azure. But luckily, IIS7 has this integrated pipeline model which Windows Azure is also using. Among other things, this means that services provided by managed modules (written in .NET) can now be applied to all requests to the server, not just ones handled by ASP.NET! In even other words: you can have some .NET code running in the same request pipeline as the FastCGI process running PHP (or Ruby). Which made me think: it should be possible to create and mount a Windows Azure Drive in a .NET HTTP module and pass the drive letter of this thing to PHP through a server variable. And here’s how...

    Note: I’ll start with the implementation part first, the usage part comes after that. If you don’t care about the implementation, scroll down...

    Download source code and binaries at http://phpazurecontrib.codeplex.com.

    kick it on DotNetKicks.com

    Building the Windows Azure Drive HTTP module

    Building HTTP modules in .NET is easy! Simply reference the System.Web assembly and create a class implementing IHttpModule:

    public class AzureDriveModule : IHttpModule
    {
        void IHttpModule.Dispose()
        {
            throw new NotImplementedException();
        }

        void IHttpModule.Init(HttpApplication context)
        {
            throw new NotImplementedException();
        }
    }

    There’s our skeleton! Now for the implementation… (Note: insane amount of code coming!)

    public class AzureDriveModule : IHttpModule
    {
        #region IHttpModule Members

        public void Init(HttpApplication context)
        {
            // Initialize config environment
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
            });

            // Initialize local cache
            CloudDrive.InitializeCache(
                RoleEnvironment.GetLocalResource("cloudDriveCache").RootPath,
                RoleEnvironment.GetLocalResource("cloudDriveCache").MaximumSizeInMegabytes);

            // Determine drives to map
            for (int i = 0; i < 10; i++)
            {
                string driveConnectionString = null;
                try
                {
                    driveConnectionString = RoleEnvironment.GetConfigurationSettingValue("CloudDrive" + i);
                }
                catch (RoleEnvironmentException) { }

                if (string.IsNullOrEmpty(driveConnectionString))
                {
                    continue;
                }

                string[] driveConnection = driveConnectionString.Split(new char[] { ';' });

                // Create storage account
                CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting(driveConnection[0]);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

                // Mount requested drive
                blobClient.GetContainerReference(driveConnection[1]).CreateIfNotExist();

                var drive = storageAccount.CreateCloudDrive(
                    blobClient
                        .GetContainerReference(driveConnection[1])
                        .GetPageBlobReference(driveConnection[2])
                        .Uri.ToString()
                );

                try
                {
                    drive.Create(int.Parse(driveConnection[3]));
                }
                catch (CloudDriveException ex)
                {
                    // handle exception here
                    // exception is also thrown if all is well but the drive already exists
                }

                string driveLetter = drive.Mount(
                    RoleEnvironment.GetLocalResource("cloudDriveCache").MaximumSizeInMegabytes, DriveMountOptions.None);

                // Add the drive letter to the environment
                Environment.SetEnvironmentVariable("CloudDrive" + i, driveLetter);
            }
        }

        public void Dispose()
        {
        }

        #endregion
    }

    Configuring and using Windows Azure Drive

    There are 4 steps involved in using the Windows Azure Drive HTTP module:

    1. Copy the .NET assemblies into your project
    2. Edit ServiceConfiguration.cscfg (and ServiceDefinition.csdef)
    3. Edit Web.config
    4. Use the thing!

    The Windows Azure tooling for Eclipse will be used in the following example.

    Copy the .NET assemblies into your project

    Create a /bin folder in your web role project and copy in all .DLL files provided. Here’s a screenshot of how this looks:

    .NET assemblies for XDrive in PHP on Azure

    Edit ServiceConfiguration.cscfg (and ServiceDefinition.csdef)

    In order to be able to mount, some modifications to ServiceConfiguration.cscfg (and ServiceDefinition.csdef) are required. The ServiceDefinition.csdef file should contain the following additional entries:

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceDefinition name="TestCustomModules" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
      <WebRole name="WebRole" enableNativeCodeExecution="true">
        <ConfigurationSettings>
          <Setting name="CloudDriveConnectionString" />  
          <Setting name="CloudDrive0" />   
        </ConfigurationSettings>
        <InputEndpoints>
          <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
          <InputEndpoint name="HttpIn" protocol="http" port="80" />
        </InputEndpoints>
        <LocalStorage name="cloudDriveCache" sizeInMB="128"/>
      </WebRole>
    </ServiceDefinition>

    Things to note are the cloudDriveCache local storage entry, which is needed for caching access to the virtual drive. The configuration settings are defined for use in ServiceConfiguration.csdef:

    <?xml version="1.0"?>
    <ServiceConfiguration serviceName="TestCustomModules" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
      <Role name="WebRole">
        <Instances count="1"/>
        <ConfigurationSettings>
          <Setting name="CloudDriveConnectionString" value="UseDevelopmentStorage=true" />
          <Setting name="CloudDrive0" value="CloudDriveConnectionString;drives;sampledrive.vhd;64" />
        </ConfigurationSettings>
      </Role>
    </ServiceConfiguration>

    The configuration specifies that a cloud drive “CloudDrive0” (up to “CloudDrive9”) should be mounted using the storage account in “CloudDriveConnectionString”, a storage container named “drives” and a virtual hard disk file named “sampledrive.vhd”. Oh, and the drive should be 64 MB in size.

    Edit Web.config

    Before the HTTP module is used by IIS7 or Windows Azure, the following should be added to Web.config:

    <modules>
      <add name="AzureDriveModule" type="PhpAzureExtensions.AzureDriveModule, PhpAzureExtensions"/>
    </modules>

    Here’s my complete Web.config:

    <?xml version="1.0"?>
    <configuration>
      <system.webServer>
        <!-- DO NOT REMOVE: PHP FastCGI Module Handler -->
        <handlers>
          <clear />
          <add name="PHP via FastCGI"
               path="*.php"
               verb="*"
               modules="FastCgiModule"
               scriptProcessor="%RoleRoot%\approot\php\php-cgi.exe"
               resourceType="Unspecified" />
          <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
        </handlers>
        <!-- Example WebRole IIS 7 Configation -->
        <defaultDocument>
          <files>
            <clear />
            <add value="index.php" />
          </files>
        </defaultDocument>

        <modules>
          <add name="AzureDriveModule" type="PhpAzureExtensions.AzureDriveModule, PhpAzureExtensions"/>
        </modules>
      </system.webServer>
    </configuration>

    Use the thing!

    Next thing to do is use your virtual Windows Azure Drive. The HTTP module adds an entry in the $_SERVER variable, named after the CloudDrive0-9 settings defined earlier. The following code example stores a file on a virtual Windows Azure Drive and reads it back afterwards:

    <?php
    file_put_contents($_SERVER['CloudDrive0'] . '\sample.txt', 'Hello World!');

    echo file_get_contents($_SERVER['CloudDrive0'] . '\sample.txt');

    Source code in PHPAzureContrib (CodePlex)

    Since there already is a project for PHP and Azure contributions, I decided to add this module to that project. The binaries and source code can be found on http://phpazurecontrib.codeplex.com.

    Other possible usages

    The approach I demonstrated above may be used for other scenarios as well:

    • Modifying php.ini before PHP runs. The module you can access would run before FastCGI runs, an ideal moment to modigy php.ini settings and such.
    • Using .NET authentication modules in PHP, check this site for an example.
    • Download updates to PHP automatically if a new version is available and deploy it into your application at runtime. Probably needs some performance tuning but this trick may work. The same goes for static content and script updates by the way. Imagine pulling a website dynamically from blob storage and deploy it onto your web role without any hassle…

    In short: endless possibilities!

    kick it on DotNetKicks.com


    Categories: ASP.NET | Azure | C# | General | PHP | Projects

    Running PHP on Windows Azure

    Yesterday I did some talks on PHP and Windows Azure at JumpIn Camp in Zürich together with Josh Holmes. Here are the slide decks and samples we used.

    Scaling Big while Sleeping Well

    Josh talked on what Windows Azure is, what components are available and how you can get started with PHP and Windows Azure.

    Running PHP in the Cloud

    I did not do the entire deck, but showed some slides and concepts. This is mainly the same content as Josh’s session with some additions.

    Windows Azure Storage & SQL Azure

    This deck talks about the different storage concepts and how to use them in PHP.

    Sample code

    As a demo, I had ImageCloud, a web application similar to Flickr. Here’s the sample code: ImageCloud.rar (5.00 mb)


    Put your existing application in the cloud!

    As promised during my talk, here's the slide deck for "Put your existing application in the cloud!".

    Abstract: "Leverage the highly scalable Windows Azure platform and deploy your existing ASP.NET application to a new home in the clouds. This demo filled session will guide you in how to make successful use of Windows Azure’s hosting and storage platform as well as SQL Azure, the relational database in the cloud, by moving an existing ASP.NET application to a higher level."

    And here's the live recording:

    Thanks for joining TechDays 2010 and my session!


    Categories: Azure | C# | Events | General | Presentations