Monday, October 23, 2017

Microsoft 70-487: Create, configure, and publish a web package

Exam Objectives

Create an IIS InstallPackage; configure the build process to output a web package; apply pre- and post- condition actions to ensure that transformations are correctly applied; include appropriate assets (web content, certificates)


Quick Overview of Training Materials




Create an IIS InstallPackage


Objective 5.1 has literally the exact same topic. Word for word... smh.  See that post.



Configure Build to output web package


As always, the Exam Ref is little help for this topic.  It focuses exclusively on using MSBuild from the command line, basically stretching what should be once sentence "Use the /T and /P options" into several anemic paragraphs.  Typical.  I found an MSDN blog post from 2009 that actually fleshed out this premise a little bit: Web Packaging: Creating web packages using MSBuild.  The "/T" switch configures the target, which refers to the MSBuild target (for web package, use "package").  The /P switch is a "property" and can actually be used to configure a number of different build settings.  One is "Configuration" which can be used to select the "Release" config instead of the default "Debug" config.

In earlier versions of visual studio, the deployment parameters (creating package as a zip file, where to create it, etc.) were apparently saved in the project file.  This seemed to manifest itself in the user interface, with VS 2012 and earlier including various settings for packaging.  Notice that the "Web Deployment Package Settings" section has some real configuration going on:



This was the same screen I noticed in the older articles and documents as well.  However, I wasn't seeing this in newer versions of Visual Studio, instead all I saw was the IIS encryption password field:



You'll see this difference too if you go to the documentation and flip back and forth between the different versions. It seems that after VS2012, these properties were moved entirely to the publishing profile (which, oddly enough, is also included in VS2012, which means you can basically configure deployments in two places).  It is still possible to configure MSBuild to package the deployment, you just have to pass it the publish profile using the /P:PublishProfile option.  There is a decent example on this StackOverflow question.  The deployment can also be triggered automatically setting the /P:DeployOnBuild argument to "true" (another SO questions addresses how to do this correctly).

The basic syntax for MSBuild on the command line would look something like this:

msbuild MyProject.csproj /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=myProfile


This functionality isn't limited to the command line.  It can be translated into an MSBuild target in configuration files.  Simple define a file called <project>.wpp.targets in the root of the project and add code similar to this:


<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         DefaultTargets="Build" ToolsVersion="4.0">

  <Target Name="Build">
    <MSBuild Projects="WebApplication3.csproj"
             Properties="Configuration=Release;
                         DeployOnBuild=true;
                         PublishProfile=IIS"
             Targets="Package"/>
  </Target>
  
</Project>


This will run MSBuild with the "Package" target, the "Release" configuration, and use the "IIS" configuration I have configured in the project (which really just means it creates a web deploy package in a deployment directory).  The above code needs work... it didn't work until I build from scratch first (I kept getting a "file not found" error and it wasn't worth chasing it down).  But judging by the SO post I based it on, it's possible to get quite a bit fancier with build based deploys.



Use pre- and post- conditions


The trick to doing any processing before or after a deployment is to use the -preSync and -postSync command line arguments.  The documentation on these operations status that they run a batch file, command file, or .exe before or after synchronization.  These operations use the runCommand provider, and the documentation for that briefly mentions that the -pre and -postSync arguments can be used to stretch the deployment pipeline, giving the example of starting and restarting a windows service:

msdeploy -verb:sync -preSync:runCommand="net stop w3svc" -source:webserver60 -dest:auto,computername=serverA -verbose -postSync:runCommand="net start w3svc"


Documentation on this topic was thin at best.  The Exam Ref wasn't much help other than pointing me in the direction of the -preSync and -postSync actions on msdeploy.  A blog post by James Crowley discusses using preSync and postSync for starting and stopping services, but puts a little bit more narrative around it than the documentation.  He notes that the runCommand provider, by default, runs with lower privilege (which is actually part of the runCommand provider documentation).

In another blog post, the author is trying to create batch files that will deploy to IIS, using AppCmd (the IIS management command line tool) to create the app and manipulate settings.  In order to ensure the IIS setup batch file has the right parameters, it uses a -preSync call to generate a batch file with all the right parameters dropped into place.

One tidbit I observered looking for better examples is that in addition to the -postSync argument, once can also use the -postSyncOnSuccess argument.  I presume this means it only executes if the deployment itself finished without error.  I tried running the -help command with MSDeploy to try and get a little insight, but just got the -preSync and -postSync help screen instead:



As far as testing app config transformations goes, I did find an interesting post that explained how to do it in a unit test essentially, eliminating the need for special packaging tasks.



Include assets (web content, certs)


There are a couple levels of inclusion (and exclusion) that may be relevant to this topic.  At the most basic level, files in the project can be included and excluded during the build phase based on the "Build Action" and "Copy to Output Directory" settings in the file properties.  A question on StackOverflow goes over the various values for "Build Action" and how it relates to what ends up in the project, and the "Copy to Output Directory" setting only has three values: Do Not Copy, Copy if Newer, and Copy Always (which are self explanatory).

The "Excluding Files and Folders from Deployment" document presents a scenario in which certain testing and debugging code should be excluded from the final deployment package.  While setting the build action to "None" is fine when we know ahead of time what files we want excluded, this doesn't support every situation.  The solution they present is to use the <project>.wpp.targets file to specify two elements, ExcludeFromPackageFolders and ExcludeFromPackageFiles.  A blog post by Ted Gustaf goes into deeper detail on how to include and exclude files in a similar way.

It is possible for Web Deploy to install certificates using the cert provider.  This provider will allow certs to be synchronized to the server as long as they meet a couple conditions.  The first is that the certificate must be marked as "Exportable", and the certificate must be stored in the Personal ("My") store.  You mark the key as exportable when you install the certificate:



The cert provider needs a source and a destination, and the syntax seems quite simple:

msdeploy -verb:sync -source:cert=my\6bb02149af180121808166c31f7837f11aeafa2a -dest:package=c:\package.zip

1 comment: