Questions? Feedback? powered by Olark live chat software
Ignorar Navegação

Writing a Site Extension for Azure Websites

Publicado em 9 setembro, 2014

Software Engineer, Azure Websites

The Azure Websites site extension feature allows developers to essentially write “apps” that can be run on an Azure Website to add administrative functionality to it. These extensions can also be published to the Site Extensions Gallery, which allows others to install and use the extension as well. Writing a Site Extension isn’t much different from writing a regular web site. The only real difference is how your code gets installed to your site.

The SCM site

Whenever you create an Azure Website, you also get a corresponding “SCM” (site control manager) site which is used for administration/debugging, and always runs over SSL. The URL for your SCM site is always the same as your default hostname, plus “scm”. For example, if my site is “demo.azurewebsites.net”, then my SCM site is “demo.scm.azurewebsites.net”. Any site extensions installed for your site can be accessed through here.

 

Writing a Site Extension and Testing it Locally

For this example, I’m going to rewrite the existing File Counter site extension as an ASP.Net MVC application using Visual Studio 2013, but you can use whatever editor you’re familiar with. You can get the code for this sample from here.

  1. Start by creating a new “ASP.Net Web Application” called “FileCounterMVC”. Choose an “Empty” template, and click the checkbox for “MVC”. (In Visual Studio 2012, you can just choose “ASP.Net MVC Empty Project” from the new project dialog)
    01-NewProject
  2. In Solution Explorer, right-click on the “Controllers” folder, and add a new “MVC 5 Controller - Empty” controller called “HomeController”.
  3. When the HomeController.cs file opens, add the following code below. The “if-else” statement allows us to run the site locally in Visual Studio. This works because Azure Websites always defines an environment variable called “home”, which contains the physical path of your public site. Since our site extension will be running from within the SCM site, we can use this variable to figure out what the physical path of our public site is. If it’s not defined, then we just assume the content folder of our site is the current sites root.
  4. using System;
    using System.IO;
    using System.Web.Mvc;
    
    namespace FileCounterMVC.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                string siteFolder;
                int fileCount;
    
                if (Environment.GetEnvironmentVariable("home") != null)
                {
                    // Maps to the physical path of your site in Azure
                    siteFolder =
                        Environment.ExpandEnvironmentVariables(@"%HOME%\site\wwwroot");
                }
                else
                {
                    // Maps to the current sites root physical path.
                    // Allows us to run locally.
                    siteFolder = Server.MapPath("/");
                }
    
                fileCount =
                    Directory.GetFiles(
                        siteFolder,
                        "*.*",
                        SearchOption.AllDirectories).Length;
    
                return View(model: fileCount);
            }
        }
    }

  5. To add a view, right-click somewhere within the “Index()” method, and click “Add View”.  In the “Add View” dialog, uncheck the “Use a Layout Page” checkbox, and click “Add”.  You should now have a view called “Index.cshtml”.
  6. Copy and paste the following code into your index view.
  7. @model int
    @{Layout = null;}
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>File Counter MVC</title>
    </head>
    <body>
        <div> 
            <h1>Your site has @Model files!</h1>
        </div>
    </body>
    </html>

  8. If we hit “F5”, we can run the app locally in IIS Express just to test that it works.  Since we’ve mapped the site folder to our local site folder, we’ll get the file count of the FileCounterMVC app. 09-debugger

 

Test your private site extension on an Azure Website

Now that we’ve tested our site extension locally, we can install it as a private site extension on an Azure Website.

  1. Add an applicationHost.xdt file at the root of the project. This file allows us to transform the applicationHost.config file used for our SCM site, with changes that our app may need. For most apps, the following applicationHost.xdt file is probably good enough to just use (except for changes to the app path), but if you would like to learn more about it, visit here. Right click on the file in solution explorer, go to properties, and make sure to set the “Copy to Output Directory” setting to “Copy if newer”.
  2. <?xml version="1.0" encoding="utf-8" ?> 
    <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
      <system.applicationHost>
        <sites>
          <site name="%XDT_SCMSITENAME%" xdt:Locator="Match(name)">
            <application path="/filecounterMVC" applicationPool="%XDT_APPPOOLNAME%" xdt:Transform="Insert">
              <virtualDirectory path="/" physicalPath="%XDT_EXTENSIONPATH%" />
            </application>
          </site>
        </sites>
      </system.applicationHost>
    </configuration>

  3. Add a file called “build.cmd” to the root of your project, and copy the following content to it.  This is a sample build script that will allow us to easily build our app, and organize it into a form that’s ready to run on a web site under the “..\artifacts” folder.  It might be good to know that running this script is functionally equivalent of doing a right-click on the “Web Application project -> publish -> To File System” action in Visual Studio.  After adding the file, run the “build.cmd” from a command prompt to build it.
  4. if not exist ..\artifacts mkdir ..\artifacts
    "%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" FileCounterMVC.csproj /p:webpublishmethod=filesystem;PublishUrl=..\artifacts /t:WebFileSystemPublish

  5. Now that we’ve built our project, we’re ready to upload it to our SCM site to test.  Open a browser and navigate to https://sitename.scm.azurewebsites.net/debugconsole.  Or, you can go to https://sitename.scm.azurewebsites.net, and then click on the “Debug Console” link.
  6. From the Debug Console, run “mkdir SiteExtensions\FileCounterMVC”.  Then navigate to the FileCounterMVC directory.  If you’re using Chrome or Firefox then you can drag-drop the content of your “artifacts” folder (shown below).  If you’re using IE, then you need to zip up the contents of the artifacts folder first, and then drag-drop the zip file on the right of the screen to have Debug Console unzip it.15-CopyToSCMSite
  7. Once the content is copied, you need to restart your site.  The easiest way is to just click on the “Site Extensions” tab at the top of the page, and then click on the “Restart Site” button.
  8. Now that you have a private version of the FileCounterMVC site extension installed, you can navigate to it by hitting the URL https://<sitename>.scm.azurewebsites.net/FileCounterMVC.  The site extension should give you the count of files in public site (not your SCM site) because we mapped the file path to the “home” environment variable.  If you add/remove files in the public site and refresh file counter site extension, you should see the file count change.If you’re wondering how the URL got mapped to “/FileCounterMVC”, you can use Debug Console to inspect the applicationHost.config file that got generated.  First navigate to: C:\DWASFiles\Sites\~1<sitename>\Config, open the “applicationHost.config.base” file by clicking on the “edit” button, and then search for the “<sites>” section.  The site entry with the “~” prepended to its name is the SCM site.  Within that site, you’ll see that there’s a bunch of apps already listed, which are preinstalled site extensions.  Now if you open the “applicationHost.config” file, which is the actual config file being used for your site, you’ll see that there’s a new app entry called “FileCounterMVC” like below.  How did this work?  Well when the SCM site loads, it looks for applicationHost.xdt files under the “SiteExtensions” folder.  If it finds it, then it uses it to transform the applicationHost.config.base file, to the applicationHost.config file with the settings you need.  Pretty neat huh?
  9. <site name="~1ehdemo" id="154213853">
      <!-- Other apps are not shown. -->
      <application path="/filecounterMVC" applicationPool="~1ehdemo">
        <virtualDirectory path="/" physicalPath="D:\home\SiteExtensions\FileCounterMVC" />
      </application>
    </site>

 

Publishing to the Public Site Extension Gallery Hosted on SiteExtensions.net

Building a private site extension is great, but wouldn’t you like to share the love? Uploading you site extension to the Site Extension Gallery allows other Azure Websites users to easily install your extension on their site. Here’s how to do it with our FileCounterMVC example:

  1. Add FileCounterMVC.nuspec to the root of your application.  Copy the content below to it and change whatever fields are necessary to match your info.  Right click on the file, go to properties, and make sure to set the “Copy to Output Directory” setting to “Copy if newer”.
    <?xml version="1.0"?>
    <package >
      <metadata>
        <id>filecountermvc</id>
        <title>File Counter MVC</title>
        <version>1.0.1</version>
        <authors>Elliott Hamai</authors>
        <licenseUrl>http://opensource.org/licenses/Apache-2.0</licenseUrl>
        <projectUrl>https://github.com/projectkudu/FileCounterMVC</projectUrl>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>A sample mvc Site Extension that counts the number of files in the web root</description>
        <iconUrl>https://raw.githubusercontent.com/projectkudu/FileCounterMVC/master/FileCounter50x50.png</iconUrl>
        <tags>filecounter sample siteextension</tags>
      </metadata>
      <files>
        <file src="**\*.*" target="content" />
      </files>
    </package>
  2. Run “build.cmd” to rebuild the project into the “artifacts” folder.
  3. Download nuget.exe command-line utility from here: http://docs.nuget.org/docs/start-here/installing-nuget.
  4. From the “artifacts” folder, run the following command to generate a NuGet package (FileCounterMVC.1.0.1.nupkg) under the parent directory:
    nuget pack FileCounterMVC.nuspec -outputdirectory ..\ –nopackageanalysis
  5. Open a browser and navigate to https://www.siteextensions.net/
  6. Login, or register for a free account.  Then navigate to the “Upload Site Extensions” link.
  7. Add your nupkg package that you created earlier, and then click “upload”19-UploadSiteExtension2
  8. The next page will ask you to verify a bunch of information about the package you’re adding.  At the bottom it will ask “Listed in Search Results”.  If you choose “yes”, then your site extension will be publically listed in the Site Extension gallery.  For our demo, we’ll choose “yes” and then “submit”.

    20-UploadSiteExtensionpublish

Installing Your Site Extension through the Azure Site Extension Gallery

Now that we’ve published our site extension, we can install it to our site.

  1. First, use the Debug Console to delete the FileCounterMVC folder from your site to make sure there’s nothing there.
  2. Navigate to “portal.azure.com” -> “Browse Websites” -> “Site Name”.
  3. At the bottom of your site blade, click on the part called “Extensions”, and then “Add”21-AzureGallery
  4. You’ll find the new extension in the list of options.  Select it, agree to the terms, and then click “ok”.  This will install the site extension and restart your site, just like how we did manually.22-azuregallery-clean
  5. After the portal reports “success”, you can open the “Installed Site Extensions” blade, and click on the “File Counter MVC” extension.  In the new blade, click “browse” navigate directly to the extension to verify that it works.23-siteextensionbrowse

Publishing to a Private Site Extension Gallery Hosted on MyGet

If you would rather not make your site extension available publically, or would rather test out the entire workflow without having to commit to using SiteExtensions.net, you can configure your site to use a private feed. In this example, I’m going to walk you through using a private MyGet feed to host my site extension.

  1. Open a browser and go to http://www.myget.org/.
  2. Login or sign up for an account if you don’t have one.
  3. Create a new feed and click on the “Add a Package” button.24-myget-upload
  4. Choose the nupkg package that we created earlier and click “Add”
  5. Go to the “Feed Details” page, and take note of your “feed URL”25-myget-copyfeed
  6. Go back to https://portal.azure.com.  Open your site blade, and click on the “Site Settings” part.
  7. In the “Site Settings” blade, add an app setting called SCM_SITEEXTENSIONS_FEED_URL, and set its value to your MyGet feed.  Then click “save”.26-portal-appsetting
  8. After you get a “Success” message, click on the “Extensions” part in under the “Site” blade, and add your extension like before.  You’ll notice that the list of extensions is smaller than usual because it should now be showing only what’s available on your feed, plus a few other special extensions.
Web