Visual Studio 2010 a de superbes nouvelles fonctionnalités de publication de projets Web qui vous permettent de publier facilement votre projet d'application Web en un clic. En coulisses, la transformation du Web.config et la création de packages sont effectuées par un script MSBuild massif importé dans votre fichier de projet (trouvé à l'adresse: C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets). Malheureusement, le script est énormément compliqué, désordonné et non documenté (en dehors de quelques commentaires mal orthographiés et largement inutiles dans le fichier). Un grand organigramme de ce fichier et quelques documentation sur comment s'y connecter serait agréable, mais semble malheureusement manquer (ou du moins je ne peux pas le trouver).
Malheureusement, cela signifie que la réalisation de la publication via la ligne de commande est beaucoup plus opaque qu'elle ne devrait l'être. J'ai été surpris par le manque de documentation dans ce domaine, car de nos jours de nombreuses entreprises utilisent un serveur d'intégration continue et certains font même le déploiement automatique (ce que les fonctionnalités de publication de VS2010 pourraient grandement aider), donc je pensais que rendre cela possible (facilement !) aurait dû être une exigence principale pour la fonctionnalité.
Quoi qu'il en soit, après avoir fouillé le fichier Microsoft.Web.Publishing.targets pendant des heures et m'être cogné la tête contre le mur des essais et erreurs, j'ai réussi à comprendre comment Visual Studio semble réaliser sa magie d'un clic avec les fonctionnalités "Publier sur le système de fichiers" et "Créer un package de déploiement". Je vais me plonger un peu dans le scripting MSBuild, donc si vous n'êtes pas familier avec MSBuild, je vous suggère de consulter cette page MSDN pour une introduction.
Publier sur le système de fichiers
Le dialogue Publier sur le système de fichiers de VS2010 m'a pris un certain temps à comprendre car je m'attendais à ce qu'une utilisation sensée de MSBuild se produise. Au lieu de cela, VS2010 fait quelque chose d'assez bizarre : il appelle MSBuild pour effectuer une sorte de demi-déploiement qui prépare les fichiers de l'application Web dans le dossier obj de votre projet, puis il semble procéder à une copie manuelle de ces fichiers (c'est-à-dire en dehors de MSBuild) dans votre dossier de publication cible. C'est vraiment un comportement étrange car MSBuild est conçu pour copier des fichiers (et d'autres choses liées à la construction), donc cela aurait du sens si tout le processus était juste une cible MSBuild que VS2010 appelle, pas une cible suivie d'une copie manuelle.
Cela signifie que le faire via MSBuild en ligne de commande n'est pas aussi simple que d'appeler votre fichier de projet avec une cible particulière et de définir quelques propriétés. Vous devrez faire ce que VS2010 aurait dû faire : créer vous-même une cible qui réalise le demi-déploiement puis copie les résultats dans le dossier cible. Pour modifier votre fichier de projet, cliquez avec le bouton droit sur le projet dans VS2010, cliquez sur Décharger le projet, puis cliquez à nouveau avec le bouton droit et cliquez sur Modifier. Faites défiler vers le bas jusqu'à trouver l'élément Import qui importe les cibles d'application Web (Microsoft.WebApplication.targets; ce fichier lui-même importe le fichier Microsoft.Web.Publishing.targets mentionné précédemment). En dessous de cette ligne, nous ajouterons notre nouvelle cible, appelée PublierSurSystèmeDeFichiers:
Cette cible dépend de la cible PipelinePreDeployCopyAllFilesToOneFolder, que VS2010 appelle avant de faire sa copie manuelle. Après avoir fouillé dans Microsoft.Web.Publishing.targets, on voit que l'appel de cette cible provoque la mise des fichiers du projet dans le répertoire spécifié par la propriété _PackageTempDir.
La première tâche que nous appelons dans notre cible est la tâche Error, sur laquelle nous avons placé une condition qui garantit que la tâche n'a lieu que si la propriété PublishDestination n'a pas été définie. Cela vous rattrapera et interrompra le build en cas d'oubli de spécifier la propriété PublishDestination. Nous appelons ensuite la tâche MakeDir pour créer ce répertoire PublishDestination s'il n'existe pas déjà.
Nous définissons ensuite un élément appelé FichiersAPublier qui représente tous les fichiers trouvés sous le dossier _PackageTempDir. La tâche Copy est ensuite appelée, qui copie tous ces fichiers dans le dossier de destination de la publication. L'attribut DestinationFiles sur l'élément Copy est un peu complexe ; il effectue une transformation des éléments et convertit leurs chemins en nouveaux chemins racinés dans le dossier PublishDestination (consultez les Métadonnées d'éléments bien connues pour voir ce que signifient ces %()).
Pour appeler cette cible depuis la ligne de commande, nous pouvons maintenant simplement exécuter cette commande (en changeant évidemment le nom du fichier de projet et les propriétés selon vos besoins) :