Build 2015 – dag 2

Om Build keynote dag 1 i mångt och mycket handlade om att annonsera en mängd spännande nyheter, handlade keynote dag 2 mer om hur du kan använda teknikerna, med fler hands on kod-exempel i Visual Studio som visade hur man faktiskt bygger Universal Platform-appar.

Men vi fick också veta att nu finns det som hintades om i gårdagens Holo Lens demo med en Raspberry Pi tillgängligt: Windows 10 IoT Core. Goda nyheter för oss som har väntat på att få köra Windows på Raspberry 2 eller Arduino.

En annan sak som överraskade positivt var att Microsoft nu satsar hårdare på media och audio-API:er för Windows. Kul också att det svenska företaget Propellerhead lyftes fram som exempel på keynoten.

Andra nyheter som presenterades var Vorlon för att fjärrdebugga javascript, Project Oxford som tillhandahåller REST-api:er från Microsoft Research för ansiktsigenkänning, taligennkänning, bildanalys och språkförståelse samt GitHub Enterprise for Azure.

how-old.net

how-old.net

En rolig demosajt som heter how-old.net har gjorts tillgänglig för att visa på styrkan i dessa API:er samt Azure Stream Analytics. Den drog klädsamt av 7 år på min ålder när jag testade den :-)

En stor del av keynoten handlade också om Internet of Things och Machine Learning, illustrerat med uppkopplade kossor. En Microsoft-chef som jag inte sett tidigare, Joseph Sirosh,  höll i denna del – och han var helt briljant talare. Du kan se en tidigare inspelning av samma föredrag här.

Inte lika många kioskvältare på dag 2:s keynote, utan mer praktiskt hands on demonstrationer, men ändå med tillräckligt mycket nyheter insprängda för att hålla igång känslan av ett Microsoft som nu ligger långt ovanför konkurrenter vad gäller innovationshöjd.

 

Build 2015 – dag 1

I den inledande keynoten på Build 2015 så märktes tydligt hur viktig Azure-plattformen har blivit för Microsoft. Efter en kortare inledning av Microsofts VD Satya Nadella fick moln-chefen och utvecklar-idolen Scott Guthrie ta över scenen. Han inledde med några intressanta och imponerande fakta – bland annat:

  • Det finns nu över en miljon servrar i Azure-klustret
  • 1,4 miljoner SQL Databases körs i Azure
  • 425 miljoner användare finns registrerade i Azure Active Directory

Därefter var det dags för att visa och demonstrera applikationsbehållar-tekniken Docker i Azure med Dockers VD och Azure CTO:n Mark Russinovich. Docker, som nu också går att köra i Windows, kommer att få stor betydelse för distribuering och skalning av lösningar i Azure framåt.

Sedan klev utvecklar-idol och Scott nummer 2 upp på scenen: Scott Hanselman. Hanselman körde en demo av Azure App Service och visade en ny Android emulator i Visual Studio.

Men den riktigt stora skrällen var när han demonstrerade ett helt nytt IDE som går att köra både i Linux, Mac och Windows: Visual Studio Code. Programmet i sig är en Node.js-applikation skriven i TypeScript/JavaScript. Eftersom Microsoft själva använder själva Visual Studio Code för att utveckla Visual Studio Code så lämpar den sig utmärkt för just Node.js-utveckling (men är inte begränsad till det).

Därefter ägnade han en stund åt ett gäng spännande nyheter för Azure SQL Databases och data-plattformen i stort:

  • SQL Data Warehouse – data warehouse som en tjänst
  • Transparent Data Encryption för att förenkla kryptering av data i Azure SQL Databases
  • Fulltext-sök i Azure SQL Databases. När det gäller sök tycker jag man först och främst ska kolla på Azure Search som alternativ, men för legacy-system kan det vara intressant.
  • Azure Data Lake för att lagra och arbeta med stora mängder ostrukturerad data.
  • SQL Database elastic pool. Det här är en riktigt intressant funktion för de scenarion där man hanterar en databas per kund/avdelning/område och behöver kunna dimensionera dessa utifrån varierande användningsgrad. Med elastic pool kan du säga att du vill ha en resurspool med en viss nivå av garanterad prestanda och de ingående databaserna delar på denna prestanda.

Hanselman lämnade sedan scenen och det var dags för en kortare demo av några nyheter i Office bl.a. kring SAP-integration.

Sedan var det dags för det som många hade väntat på: nyheterna för utvecklare i Windows 10.

Terry Myerson berättade om den gemensamma Windows Store som kommer finnas för alla versioner av Windows oavsett vilken device det körs på samt Windows Store for Business för att möjligöra publicering av interna företags-appar.

Därefter om de fyra olika sätten som du kan utveckla Universal Windows Apps på – appar som kommer kunna köras i Windows, Windows Phone och kommande versioner av Windows:

  1. Webb-sajter. Kapsla in din webb-sajt och kör som en app.
  2. Win32 and .NET. Det blir nu möjligt att använda dina befintliga Win och .NET-kunskaper även för Store-appar.
  3. Java och C++ från Android-appar. Windows Phone får möjighet att exekvera kod från Android-appar. Fortfarande rätt oklart exakt vilka begränsningarna blir för detta, men förmodligen så finns det ett antal specifika API:er som inte är direkt portabla,
  4. Objective-C för iOS. Genom ett verktyg kan du porta ett Objective-C-projekt till en Visual Studio-solution som sedan kompileras och kan köras i Windows Phone. Även här råder viss oklarhet exakt vilka begränsningarna kommer att vara.

Efter det tog Joe Belfiore över scenen. Han är en av mina favorit-presentatörer vad gäller Windows-delarna från Microsoft, kör alltid med en avslappnat skön stil, utan att vara insäljande.

Den liten skräll för en tid sedan var att Internet Explorer kommer upphöra som varumärke – nu annonserades vad namnet på webbläsaren i Windows 10 kommer att bli: Microsoft Edge.

Joe snackade lite med Cortana, visade lite av det nya Windows 10-gränssnittet och annonserade den nya imponerande ‘Continuum for phones’-funktionen som betyder att du kan köra ut program från telefonen på en stor skärm, koppla in tangentbord & mus och arbeta med dem som om du hade en dator.

Holo Lens Demo

Holo Lens Demo

Därefter avslutades keynoten med några fullkomligt lysande demos av Microsoft Holo Lens, vilket fick en fullkomlig våg av ha-begär skölja genom publiken – otroligt cool teknik med massvis med intressanta tillämpningar.

Det ska bli mycket intressant att se vad keynote dag 2 på Build har att bjuda på, jag misstänker att Microsoft kan ha ytterligare några äss i rockärmen att förvåna folk med.

Internet of things: Lego-robotar, Azure och Raspberry Pi

Active Solution där jag arbetar är ett väldigt kunskapsintensivt företag. Det vi gör är ju att erbjuda vår kompetens och långa erfarenhet till våra kunder för att hjälpa dem skapa lösningar. Då vill det till att vi håller våra verktyg vässade, hela tiden är på tårna och lär oss mer om ny teknik, nya metoder och förbättrar processer.

Under förra året beslutade vi oss därför för att satsa på något lite annorlunda vad gäller kompetensutveckling. Vi valde att skapa ett antal forsknings- och utvecklingsprojekt, för att tillsammans arbeta med saker som kanske ligger lite utanför det vi gör i vanliga kundprojekt. Hela tiden med målet att dela med oss av våra lärdomar och att arbeta tillsammans med nya roliga tekniker och metoder.

Det här resulterade i flera intressanta projekt med spännande resultat, bl.a. en Team Dashboard som en Chrome Cast-applikation med uppdateringar från Visual Studio Online som kan berätta när du tagit sönder bygget (självklart med Javascript-baserad talsyntes :-) samt att vi blev det första företaget i Sverige som migrerade en EPiServer site i produktion till Azure Web Sites. Det har varit grymt kul, inspirerande och lärorikt att ta del av de olika projekten under våra gemensamma luncher där de olika teamen fått berätta om sina lösningar i “lightning talk”-stil.

LegoMindstormsRobot

Ett av projekten har gått ut på att koppla ihop Lego Mindstorms-robotar med Raspberry Pi-datorer och kontrollera dessa över Internet via Azure.
Kring det här har vi även byggt ett spel som vi har tagit med oss på ett antal konferenser, TechDays, TechX och nu senast den fantastiskt trivsamma Swetugg-konferensen. Vi har fått väldigt många förfrågningar om vi inte kan lägga upp en beskrivning av hur vi integrerat robotarna med Raspberry Pi och hur vi styr dem, så här kommer en beskrivning av lösningen.
All kod som körs i robotarna finns tillgänglig på GitHub.
Själva robotarna består av tre delar:
1. Lego Mindstorms. Delar ihopbyggda från Legos EV3-modell av Mindstorms, i vår egen-patenterade proffsiga Robot-design.
2. Raspberry Pi B med Wifi-dongel. Wifi-donglarna har vi märkt är i lite varierande kvalitet och funkar olika bra med Raspberry Pi. Asus Wifi-donglar har vi märkt fungerar bra med Raspberry Pi B.
3. BrickPi. BrickPi är ett specialbyggt kort för att styra Lego-robotens motorer och läsa av sensorer via en Raspberry Pi. Går att beställa från Robotshopen.se http://www.robotshopen.se/se/art/brickpi-starter-bundle.php
Styrningen av Robotarna sker via en vanlig webbsida som körs i en Azure Web Site. Via Ajax-anrop så skickas meddelanden ut via en SignalR hub. http://signalr.net/
I Raspberry Pi:n kör vi sedan en Node.Js-server som använder ett SignalR-paket för att koppla upp sig via webbsockets mot Azure-siten. När ett meddelande tas emot via SignalR så använder vi ett färdigt C-bibliotek från BrickPi för att kommunicera styrmeddelanden till motorerna.
Här finns en film som beskriver lösningen:

Vi använder även Microsofts Azure SDK för Node.js för att kontinuerligt skicka ”heatbeat”-meddelanden till Azure ServiceBus – för att kontrollera att robotarna lever och är igång.
Från början trodde vi att styrningen av robotarna också skulle kunna hanteras genom att skicka meddelanden via Azure ServiceBus. Det visade sig dock att fördröjningen blev alldeles för lång när vi gjorde så. Det beror inte på ServiceBus:en i sig (den har en fördröjning som mäts i millisekunder) utan berodde på implementationen i Node.js-paketet. I många fall kan man ju leva med en fördröjning på ett par sekunder, men det funkade dåligt för att styra robotar…

Runt vårt Robot-scenario så byggde vi också ett spel: CandyPush. Det går ut på att låta två robotar tävla mot varandra för att putta ner så mycket godis i två hål i en spelplan som möjligt under tidsbegränsning. Sedan har vi två USB-kopplade vågar under spelplanen som mäter hur mycket godis som puttats i. Vågarnas resultat skickas upp i Azure Storage för att avgöra resultatet.

CandyPush in action!

För att prata med vågen används Hid Library, ett generellt bibliotek för kommunikation med USB-enheter. Kod och info finns på github, github.com/mikeobrien/HidLibrary; NuGet-paket under namnet Hid Library.
Enhetens identitet utgörs av tillverkarens Vendor ID samt modellens Product ID. Förutom dessa måste man känna till formen på data som levereras från enheten. I övrigt är kommunikationen enkel.
I nedanstående demokod scannar vi efter anslutna enheter som matchar vågens identitet. Vi initierar kommunikationen och anropar ReadReport med en callback som anropas då vågen har ett värde att rapportera (vilket sker ca 2 ggr per sekund). I call back-metoden ReadHandler kan aktuellt mätvärde läsas ut.

public class Program
{
    private static HidDevice device;

    private static void Main(string[] args)
    {
        ConnectScale();
        Console.ReadLine();
    }

    private static void ConnectScale()
    {
        const int DymoVendorId = 0x0922;
        int[] M5ProductIds = { 0x8005 };

        device = HidDevices.Enumerate(DymoVendorId, M5ProductIds).First();
        // We assume at least one connected scales.

        device.OpenDevice();
        device.ReadReport(ReadHandler);
    }

    private static void ReadHandler(HidReport report)
    {
        if (report.ReadStatus == HidDeviceData.ReadStatus.Success)
        {
// Byte 4-5 contains current scales reading
            var weight = BitConverter.ToUInt16(report.Data, 3);
Debug.WriteLine("Vikt: {0} g", weight);
        }

        device.ReadReport(ReadHandler); // Poll again 
    }
}

Här hittar du koden för att integrera Lego-robotarna med Azure.

TechX Azure – Introduktion till Azure SQL Database

Idag hade jag förmånen att få medverka på Microsofts Azure TechX-konferens. Konferensen var fullsatt med över 250 deltagare som tagit sig till Microsofts kontor utanför Kista för att få ta del av tre parallella spår under två dagar fullspäckade med intressanta dragningar. Kul!

Den mest spännande dragningen jag själv gick på tyckte jag var Robert Lucianis föredrag om Machine Learning. Grymt intressant, inte bara ur ett specifikt teknikperspektiv, utan om något som kommer omvälva hela vår arbetsmarknad – i takt med att smarta maskiner kommer ta över mer och mer av vad vi gör idag. Tyvärr så spelade inte just den sessionen in, men du kan se en intro film om ML i Azure på Channel9 här.

Precis som på TechDays hade vi även med oss vårt IoT-robotprojekt, med uppkopplade legorobotar, vågar och “Candy Push”-godistävling: TechXRobot

Introduktion till Azure SQL Database

Min egen session handlade om Azure SQL Databases. Powerpoint-bilderna som jag visade finns här: Introduktion till Azure SQL Database.pptx.

I presentationen nämnde jag en viktig aspekt: nämligen vad som INTE stöds i Azure SQL Database idag. Här finns Microsofts dokumentation kring vad som inte stöds i Azure SQL Database idag.

De demos jag gjorde av SQL Management Studio var gjorda med Management Studio 2014 samt en uppdatering som gör det möjligt att bland annat högerklicka och välja “Edit Top 200 rows” och “Design” precis som du är van vid från lokala SQL-databaser. En bra genomgång av vad som är nytt i Azure SQL Databases med den nya v12-versionen (som alltså motsvarar SQL Server 2014) finns här.

För att undersöka resursutnyttjandet jämfört med de “DTU”:er, Database Throughput Unit – som du har tillgång till i en viss version av Azure SQL Database så körde jag följande script (finns tillgängligt på MSDN här):

-- dm_db_resource_stats

SELECT
AVG(avg_cpu_percent) AS 'Average CPU Utilization In Percent',
MAX(avg_cpu_percent) AS 'Maximum CPU Utilization In Percent',
AVG(avg_data_io_percent) AS 'Average Data IO In Percent',
MAX(avg_data_io_percent) AS 'Maximum Data IO In Percent',
AVG(avg_log_write_percent) AS 'Average Log Write Utilization In Percent',
MAX(avg_log_write_percent) AS 'Maximum Log Write Utilization In Percent',
AVG(avg_memory_usage_percent) AS 'Average Memory Usage In Percent',
MAX(avg_memory_usage_percent) AS 'Maximum Memory Usage In Percent'
FROM sys.dm_db_resource_stats;

Följande SQL-script är intressant om du vill undersöka en äldre “Web”- eller “Business”-version av Azure SQL Database för att se vad den motsvarar i den nya modellen:


-- DTU mapping, kan bara köras i gamla Web/Business Master db
WITH DTU_mapping AS
( SELECT *
FROM ( VALUES (1, 10,'Basic'), (2, 20,'S0'), (3, 40,'S1'), (4, 100, 'S2')
, (5, 200, 'P1'), (6, 400,'P2'), (7, 1600, 'P3')
) AS t(id, percent_of_S2, target_edition)
), rc as
( SELECT start_time, end_time
, (SELECT Max(v)
FROM (VALUES (avg_cpu_percent)
, (avg_physical_data_read_percent)
, (avg_log_write_percent)
) AS value(v)) as [avg_DTU_percent]
FROM sys.resource_stats
WHERE database_name = 'NamnPåDinDB'
)
SELECT rc.*
, (SELECT TOP(1) t.target_edition
FROM DTU_mapping AS t
WHERE t.percent_of_S2 > CAST(1.2*rc.avg_DTU_percent as int)
ORDER BY t.percent_of_S2) as target_edition
FROM rc;

En utförlig artikel om hur du ska dimensionera Web och Business-version finns här.

Slutligen så visade jag en demo av Elastic Scale som hjälper dig att skala ut Azure SQL Databases på flera instanser. Den demo jag visade på utskalning av Azure SQL Dataabases finns här.

TechDays 2014

Förra veckan medverkade Active Solution på Sveriges största Microsoft-konferens TechDays. Vi medverkade i Microsofts monter och visade vårt Internet of Things-influerade spel “Candy Push Saga”, som gick ut på att via mobilen styra två robotar – som kommunicerade via Webbsocket mot en Azure Web Site. Spelet gick ut på att putta ner godisar i två hål i spelplanen. Godisar som vägdes av vågar under hålen – vågar som naturligtvis också var uppkopplade mot Azure och lagrade resultatet i table storage.

Candy Push Saga

“Candy Push Saga” in action på Techdays.

Jag gjorde ett litet inhopp innan keynote och hjälpte Dag König och Joachim Nässlander att värma upp inför keynoten med lite frågespel om programmeringsspråk man minns (eller kanske glömt i mitt fall :-) Kul var det hursomhelst.

Jag medverkade också i en intressant paneldebatt om molnets påverkan på arkitektur och utvecklingsprocesser tillsammans med Magnus Mårtensson, Sten Sundblad, Fredrik Normen och Dag König. Den kommer förhoppningsvis publiceras via Dag Königs blogg inom kort. Edit: här är direktlänken till vår paneldebatt.

Sedan körde jag en session om Azure Web Sites sista passet dag 2. Tack alla som kom till den sessionen trots att det var sent på dagen och sista passet! Den kod som jag demade finns tillgänglig här och de powerpoint-bilder jag visade finns här.

Presentation från DevSum14 – Azure Web Sites IRL

Idag talade jag på den som alltid mycket trivsamma konferensen Developer Summit. Min presentation handlade om Windows Azure Web Sites utifrån tre olika kundprojekt vi har arbetat med på Active Solution.

Bilderna från min presentation finns här.

Det demoprojekt som jag visade finns här.

Tack Cornerstone för ännu en lyckad DevSum-konferens!

ClickOnce deployment using TeamCity (without getting too dirty)

Whenever you are doing continuous build and/or deployment you always want to keep the amount of installation and configuration you have to do on each build agent to an absolute minimum. There are a number of reasons for this: to be able to scale out by easily adding new agents without having to worry about pre-requisites, to minimize the need for documentation around special setups and risk hard person dependencies, to cut the time for setting up new build environments .

Ideally everything you need to build the project should be fetched from the source repo or some other storage. Unfortunately this is really hard to accomplish and you often end up going the “dirty route” of installing different SDK: s or even Visual Studio on the build machines.

The above is very true when it comes to automating ClickOnce deployments.
It is actually really fascinating how a technology especially designed to help with deployment scenarios is so darn hard to automate in a sane way.

At Active Solution we use TeamCity for the majority of our builds and automated deployments. TC is a really nice solution – a breeze to install and setup, has a friendly intuitive user interface that makes it easy to create new build definitions and the build server is rock solid with very few issues.

In one project I’ve been involved in recently we wanted to automate the deployment of an old WinForms ClickOnce application – deployed to the users through a web site. This posed a couple of challenges:

    • The ClickOnce deployment mechanism is dependent on a binary being installed as part of the Visual Studio installation.
  • You need a way to increment the version number for the application, and to set that version number in the ClickOnce manifest.

 

  • Preferably you also want to reflect this version number in the HTML page that you install the application from.

 

  • The ClickOnce manifest has to be signed with a certificate.

 

To accomplish this we created an MSBuild script that essentially:

    1. Copies the binaries needed by MSBuild to do a ClickOnce deploy from source control to the root folder of the ClickOnce project.
  • Reads the version number from a shared Assembly info file.

 

  • Builds the solution and does a ClickOnce publish to disk locally on the build agent.

 

  • Copies the published folder + HTML install page to a target directory

 

  • Updates the HTML install page with the correct version number.

 

After that, the catalogue is ready to be XCopy deployed to the server; this is done as a separate build step.

Below is the script. The comments in the script are pretty self-explanatory – but maybe a couple of things need an explanation:

Removing the need for installing VS/.NET SDK
“Copy the required ClickOnce build engine files” – where on earth does these come from??? Turns out ClickOnce is hardwired to search for build engine files that come with the VS or SDK installation. These files can reside under a couple of different locations described here: http://blogs.msdn.com/b/emmamou/archive/2009/04/08/team-build-for-clickonce-application-with-bootstrapper.aspx

This is where they reside on my dev box:

ClickOnce Engine file path

However – if it doesn’t find the installation path in the registry it tries to find the files in a catalogue called ‘Engine’ in the project root. So we just checked these files to source control and then copy them from there in the build process.

What is SharedAssemblyInfo?

We read the version number from a file called SharedAssemblyInfo.cs – but what is that?
SharedAssemblyInfo is a way to share the version number (and other information about assemblies) across several projects by linking to a shared assembly info file : http://theburningmonk.com/2010/03/net-tips-use-a-shared-assemblyinfo-cs-for-your-solution/

We could have used TeamCity’s incremented version number, but in this case we wanted to set the version number across all related assemblies by hand – but we only need to change it in one place.
We then use this technique to parse the assembly version from the file: http://stackoverflow.com/questions/2042350/how-to-read-the-assemblyversion-from-assemblyinfo-cs

The Build script also make use of functions found in the MSBuild Community Tasks – we have checked the MSBuild.Community.Tasks.dll and targets into to source control as well.

Here is the GitHub gist with the script: These are the settings for the TeamCity build step: Team city build step
The only really interesting setting here is the OutputPath which tells ClickOnce where to output the publish – in our case we set the name of the catalogue to the current build configuration (Staging).

There is still one thing that we have to install by hand on the build agents: the signing certificate.
An improvement would be to build the manifest with the help of Mage: http://msdn.microsoft.com/en-us/library/acz3y3te.aspx – with Mage we could use the –CertFile filePath parameter and have the certificate checked into source control as well. Pease let me know if there is another/better way of doing this.

But still: we can now build and deploy our ClickOnce application without getting too dirty and installing VS/.NET SDK:s on the server: Robert – ClickOnce 1 – 0! (or maybe that should be Robert – ClickOnce 1 – 11 :-)

Original blog post from my old blog – filed under: TeamCity, english, ClickOnce

Microsoft släpper IaaS-tjänsten ‘Windows Azure Infrastructure Services’

Idag annonserades att den hett efterlängtade IaaS-tjänsten i Windows Azure – som nu fått namnet ‘Windows Azure Infrastructure Services’ – har nått det man kallar för ‘General Availability’ – det vill säga att tjänsten nu är definitivt lanserad och supporteras brett mot alla kunder.

Microsoft har nu realiserat visionen om det dynamiska datacentret – där kunder kan skapa och köra virtuella maskiner lokalt, för att sedan enkelt flytta dessa till molnet och tillbaka vid behov.

Det här kommer naturligtvis ge många nya möjligheter för Microsoft-teknikinriktade företag och organisationer som vill bygga nya tjänster med befintliga produkter, flytta redan existerande lösningar till molnet eller skapa hybridlösningar där delar av lösningen utnyttjar fördelarna med Windows Azure.

Men målgruppen för Windows Azure Infrastructure Services är bredare än så. Bland de färdigpreppade virtuella maskiner som finns att tillgå i tjänsten finns också ett antal färdiga Linux-distributioner. Microsoft har ambitionen att ta en rejäl del av marknaden för att köra även Linux-baserade system i molnet.

Det har under en längre tid pågått en märkbar prispress mellan Microsoft och Amazon. I samband med det här släppet passar Microsoft också på att annonsera prissänkningar – både på virtuella maskiner och plattformstjänster med 21 – 33%. Detta förutsatt att du bokar upp dig för 6 eller 12 månaders användning av tjänsterna.

I samband med detta annonserades också två nya intressanta storlekar på virtuella maskiner: en med 28 GB minne och 4 cores processor och en med hela 56 GB minne och 8 cores processor – för de större, minnesslukande och mer krävande applikationer.

Windows Azure blir nu en mycket stark utmanare till Amazon AWS även på IaaS-området, ett område där Amazon tidigare har varit starkt dominerande. Något som talar för Microsoft är möjligheten att få all support samlad hos en och samma leverantör – oavsett om det gäller applikationsplattformen – Sharepoint, BizTalk, SQL Server – eller det underliggande operativsystemet eller själva driften av dessa. När du utnyttjar Windows Azure Infrastructure Services för att köra Microsoft-produkter kommer du kunna vända dig till en och samma leverantör, något som naturligtvis är högintressant för många kunder som vill konsolidera sina miljöer och ensa bland sina leverantörer.

Läs mer på Windows Azure-teamets blogg: http://blogs.msdn.com/b/windowsazure/archive/2013/04/16/the-power-of-and.aspx

Category: azure