Arkiv för April 2nd, 2012
Here are the steps you need to take in order to put .NET Framework 4.5 Beta and ASP.NET MVC 4 on Windows Azure and run it in a Web Role.
First of all; Why would you want to do that? Well if you need to ask that question then you are not really a geek! ;~) Because we can! Honestly if you want to start testing the latest bits on the real Windows Azure Cloud, which may be something you want to consider, it can be done using this post.
That being said, just because you can do something it does not mean you should! Which brings me to my second point before I start showing you how to actually do this: This works on my (virtual Windows Azure) machine and it should work on yours. Keep in mind that this is beta software and it should not be put into production. Now that you have read this disclaimer you will probably just go ahead and do what ever you want any way. But now you can’t blame me. ;~)
Kind of unrelated side note: I promised this blog post on the twitters: “So I had some fun with WindowsAzure today. Now all I gotta do is write the blog post! * feeling secretive *”. This is the post I promised. Now I have another problem. I am writing this from my //build/ Samsung Slate because I have shipped my work laptop of to maintenance. I might have some difficulties with creating screen shots and getting correct syntax highlighting in my post below. We’ll just have to make do. In fact as I type this I am installing VS 2010 Express on my Slate.
Kind of related side note: If nothing else this post is a walk through of a bunch of Windows Azure functionality including start up tasks, packaging (using cspack), publishing (using Windows Azure Cmdlets) and so forth. As such I hope this post gives you some value for reading it.
Here are the basic steps we need to take:
1) Create your ASP.NET MVC 4 Beta Application using Visual Studio 11 Beta. I know – lots of betas here but hey it’s a Beta world out there. Live it and learn to love it!
2) Create a Windows Azure Service Definition file and a Service Configuration file. There’s a trick to making this step easy which you will see below.
3) Add a startup task to the Service definition which calls to a .cmd file.
4) Let the .cmd you created call into a .ps1 PowerShell script. This step is not strictly necessary but since power shell is cooler than a command script we might as well. ;~)
5) Write the .ps1 so that it calls the installer for .NET 4.5 Beta (& MVC 4 Beta). More about this below.
6) Include the .cmd, .ps1 and the installer mentioned in the previous step in your MVC Application from step 1.
7) Publish the MVC Application to the local file system.
8) Use the Windows Azure Command Line package utility (cspack) to pack the published MVC Application and the Service Definition file into a Windows Azure deployment package.
9) Deploy the package along with the Service Configuration file to Windows Azure.
Now Windows Azure takes over and if you have completed the steps correctly the installer for .NET 4.5 Beta will launch, install and complete and your MVC 4 Application will go live on Windows Azure!
This is the end result we are aiming for: (Look at the address bar and you’ll note that we are running at netfourfivecloud.cloudapp.net which is a Windows Azure domain.)
Note: The important realization here is that if this instance needs to restart or re-image to a different Virtual Machine instance the whole deployment process is completely automated and will rerun and ‘just work’ every time.
OK – so let’s get crackin’ – step by step!
This step is easy! Install Visual Studio 11 Beta. Go: File –> New MVC 4 Application. Done!
Of course you can fill your application with any custom content you’d like and this is completely up to you. This is plain vanilla MVC Application creation.
So “Go Wild and Crazy” and do your thing!
You simply go to the Service Definition schema documentation and create a text file with XML by hand. Then, also by hand, create the Service Configuration file (using the Service Configuration schema documentation). This will configure your MVC Application in Windows Azure in accordance with what you put in your Service Definition file! Make sure the two are completely correct and match each other!
Sounds easy? No? Thought so. I’m being cheeky. While this, in theory, is very doable it is also quite tedious. You have to get it all 100% right or your Windows Azure Application will not deploy and/or function correctly. The reason you have to do this your self is that Visual Studio 11 Beta (at the time I author this post) does not support the Windows Azure tools for Visual Studio. This means that you cannot create a Windows Azure Application using Visual Studio 11 beta! (There is a lot more info on how you work with Windows Azure Applications in a joint environment with both Visual Studio 2010 and Visual Studio 11 Beta on the official Windows Azure site.)
I mentioned above that there is another trick to doing this step: Simply use Visual Studio 2010 and create a Windows Azure project with a ghost Web Application (pick any web application). You will get a Service Definition file and a Service Configuration file and full tooling support in VS 2010 to set up your files the standard way that we already know and love. The Web Application can just be left unmodified. It simply serves as a place holder for the configuration definitions that you want to pass on through the definition and configuration files to your MVC 4 Application.
This is what my solution looks like in VS 2010:
From all of these files we are only interested in two for future reference:
ServiceConfiguration.Cloud.cscfg: The configuration settings for your Windows Azure Hosted Service. Here the actual configuration setting values live. These values can be changed at run time in Windows Azure but the definition, which setting keys your application know about, are defined in the definition file.
ServiceDefinition.csdef: The Windows Azure Service Definition file where your configuration of your Windows Azure Hosted Service resides.
I also chose to configure Remote Desktop in this step but you don’t have to do that.
There is one thing I want you to set in this step manually in the Service Configuration file. Open up the ServiceConfiguration file and hand-edit it to set osFamily to be “2”. I do this on all my projects. The default template value is one. Setting it to two means things like you can use the latest version of PowerShell: “Windows Guest OS Family 2 is substantially compatible with Windows Server 2008 R2”. Here is what your file should look like:
<ServiceConfiguration serviceName="Windows_Azure_Test" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*">
By the way: For this demo I configured a single extra small instance Virtual Machine.
Now that you have your Service Definition file there are two things you need to specifically add to it.
First you have to create a startup task which calls to a .cmd file. I added by hand a custom <startup></startup> tag and content to my configuration (see below). I target a script named Startup.cmd which will be located in my MVC Application in a folder named Startup like so: /Startup/Startup.cmd. We will add this file and it’s content later.
Second you need to configure the correct Application Domain. This is actually an extra step required to configure your IIS to properly run your MVC Application. If you deploy from Visual Studio it will correctly configure the IIS on the Virtual Machine where your MVC Application deploys. But if you use cspack (which we will use below) you have to be explicit about one thing. You have to tell Windows Azure which version of .NET Framework you are targeting. Here is a potential caveat: You say you want to run .NET Framework 4.0 and this will make Windows Azure configure the IIS to run your MVC Application in an Application Domain with .NET Framework 4.0 integrated mode. After you have installed .NET Framework 4.5 Beta using a .NET Framework 4.0 Application Domain definition actually ‘just works’. So you’re not trying to configure a .NET Framework 4.5 Application Domain. I’m not really sure one exists? (Thank you Keiji Kamebuchi for pointing me to this resource to solve this issue: WebRole Schema.) The Runtime targets a named .dll. Mine was named “MvcWebRole1.dll” but yours may have another name. The important thing is that it matches the name of the assembly output for your MVC 4 application (not the one you created in VS 2010 but the one you created in VS 11 Beta).
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="Windows_Azure_Test" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="MvcWebRole1" vmsize="ExtraSmall"> <!-- The Runtime configuration. --> <Runtime> <EntryPoint> <NetFxEntryPoint assemblyName="MvcWebRole1.dll" targetFrameworkVersion="v4.0" /> </EntryPoint> </Runtime> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> </Imports> <!-- The Startup task. --> <Startup> <Task commandLine=".\Startup\Startup.cmd" executionContext="elevated" taskType="simple"> <Environment> <Variable name="EMULATED"> <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" /> </Variable> </Environment> </Task> </Startup> </WebRole> </ServiceDefinition>
Here is the .cmd file I use – We will add it to the MVC application below:
if "%EMULATED%"=="true" goto :EOF powershell -ExecutionPolicy Unrestricted ./Startup/Script.ps1 > script.ps1.log 2>&1 exit /B 0
(Also the script does not run on my local emulator – only in the Windows Azure Cloud.)
This is the entire PowerShell script. Kind of lame that I didn’t just make this call from the .cmd file, right? Well… I always call into PowerShell from my startups because I like it. And now you who read, if you didn’t know already, also know how to do it.
Invoke-Expression ".\Startup\dotNetFx45_Full_x86_x64.exe /q /norestart"
The .NET Framework 4.5 Beta redistributable package can be found here in the .NET Framework Deployment Guide for Developers.
Note I: I could have used the Web bootstrapper version but I tried it and couldn’t really make it work. Might have been a small bug or something. On the other hand it’s better if your Windows Azure deployment is not dependent on an installer which downloads content. What if that content moves.
Note II: For extra credit this installer may be uploaded by you to a Windows Azure storage blob container and downloaded from there to to your Virtual Machine during startup script time. I chose not to do that this time. This makes my Windows Azure installation package much larger. The redistributable package is 50 Mb which gets added to my installation.
Kind of in the wrong order I told you the content of a command file and a script file before I told you where to put them. Anyway… ;~) You add a folder to your MVC 4 application called Startup in this folder you add the Startup.cmd, Script.ps1 and dotNetFx45_Full_x86_x64.exe files. Then you add those files to your MVC application. All files added in this way must have properties set to “Copy to Output Directory” and “Copy always”. Look at Steve Marx post about this. We want the files copied to the output but not compiled into the application. This way they will get deployed to Windows Azure and we can use them there.
You strictly don’t have to have a /Startup folder. I simply feel it looks nicer during development time for my application.
Now the MVC application is all done and the scripts are ready. All we need to do now is publish, package and deploy!
Right click your MVC Application and select “Publish…”. Publish your application to a folder on your local file system. Mine happened to become “D:\tempsites\MVC 4 site”.
Cspack is a nifty command line package utility tool which enables you to pack Windows Azure Applications without using Visual Studio. The reason we have to use this tool is because we have our MVC Application in VS 11 Beta and our Windows Azure Application in VS 2010.
You need a Windows Azure Command Prompt (or Windows Azure SDK Shell as it is also called) to complete this step. (Or you need to reference cspack.exe as part of your Environment Path.)
I used this command to pack up my deployment:
cspack "Windows Azure Test\Windows Azure Test\ServiceDefinition.csdef" /out:azurepack\testNEW.cspkg /role:MvcWebRole1;"MVC 4 site" /sites:MvcWebRole1;Web;"D:\tempsites\MVC 4 site"
You point to the .csdef file, point out where to output the result, define the role(s) which is just the MVC one in our case and finally point out which sites you have – again we have just the one published MVC 4 Web “Site”, or Application.
When this step is done you have a .cspkg file ready to deploy to Windows Azure.
To deploy to Windows Azure you need two things.
1) The .cspkg file from the previous step, containing your MVC 4 Application, the ServiceDefinition.csdef file, the .cmd and .ps1 scripts and the .NET Framework Installer.
2) The ServiceConfiguration.Cloud.cscfg file from earlier.
The simple way to deploy to Windows Azure is to go into the Windows Azure Portal and upload both files to a new Hosted Application and you’re done.
Here is the Windows Azure Cmdlets version of the same:
New-HostedService -ServiceName "netfourfivecloud" -AffinityGroup "NorthEurope" New-Deployment -ServiceName "netfourfivecloud" -Slot "Production" -Package "D:\tempsites\azurepack\testNEW.cspkg"
-Configuration "D:\tempsites\Windows Azure Test\Windows Azure Test\ServiceConfiguration.Cloud.cscfg" -Name "NET45test"
-Label "Testing .NET 4.5 in Azure" -StorageAccount "magnus"
Note: I have already created an affinity group named “Northern Europe” with a storage account named “magnus” in my Windows Azure subscription.
Note II: I have also previously executed the following two Cmdlets once for my subscription:
Set-Subscription "Magnus Azure" -SubscriptionId "<my subscription>" -Certificate (Get-Item cert:\CurrentUser\My\<my management cert thumbprint>) Set-Subscription -DefaultSubscription "Magnus Azure"
Now Windows Azure takes over. The deployment is uploaded by me to the “magnus” blob storage account. Windows Azure then grabs that deployment from there and pulls it into the Windows Azure deployment process. A Virtual Machine is requisitioned as usual and before the Application is started on it the startup script is executed. The startup scripts calls the PowerShell script. The PowerShell script executes the .NET Framework 4.5 redistributable packages which installs the prerequisites we need.
After this the Web Application starts…
And it ‘just works’! ;~)
Want my project files? Well you have all you need here in this post and normally I’d just attach the zipped solution. Right now my system setup is in complete disarray and I cannot attach files to my Live Writer. Please contact me if you want my solution!
OK – so there are quite a few steps we need to take to make this work. But, hey, it does work! In theory it’s not even rocket science: To run the latest bits on in Windows Azure first run the installer for them!
In reality a bit tricky but totally doable.
.NET 4.5 Beta and ASP.NET MVC 4 Beta is now on Windows Azure!
Hope you will have some fun with this, let me know if you have any questions or want to show off what you have done with it! And please remember with #awesome power comes #awesome responsibility! ;~)