43 votes

Tâches avancées utilisant la transformation Web.Config

Quelqu'un sait-il s'il existe un moyen de "transformer" des sections spécifiques de valeurs au lieu de remplacer la valeur entière ou un attribut ?

Par exemple, j'ai plusieurs entrées appSettings qui spécifient les Urls de différents services Web. Ces entrées sont légèrement différentes dans l'environnement de développement et dans l'environnement de production. Certaines sont moins triviales que d'autres

<!-- DEV ENTRY -->
<appSettings>
 <add key="serviceName1_WebsService_Url" value="http://wsServiceName1.dev.domain.com/v1.2.3.4/entryPoint.asmx" />
 <add key="serviceName2_WebsService_Url" value="http://ma1-lab.lab1.domain.com/v1.2.3.4/entryPoint.asmx" />
</appSettings>

<!-- PROD ENTRY -->
<appSettings>
 <add key="serviceName1_WebsService_Url" value="http://wsServiceName1.prod.domain.com/v1.2.3.4/entryPoint.asmx" />
 <add key="serviceName2_WebsService_Url" value="http://ws.ServiceName2.domain.com/v1.2.3.4/entryPoint.asmx" />
</appSettings>

Remarquez que sur la première entrée, la seule différence est ".dev" de ".prod". Sur la deuxième entrée, le sous-domaine est différent : "ma1-lab.lab1" de "ws.ServiceName2"

Jusqu'à présent, je sais que je peux faire quelque chose comme ça dans le fichier Web.Release.Config :

<add xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" key="serviceName1_WebsService_Url" value="http://wsServiceName1.prod.domain.com/v1.2.3.4/entryPoint.asmx" />
<add xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" key="serviceName2_WebsService_Url" value="http://ws.ServiceName2.domain.com/v1.2.3.4/entryPoint.asmx" />

Cependant, chaque fois que la version de ce service Web est mise à jour, je devrais également mettre à jour la configuration Web.Release.Config, ce qui va à l'encontre de l'objectif de simplification des mises à jour de ma configuration Web.

Je sais que je pourrais aussi diviser cette URL en différentes sections et les mettre à jour indépendamment, mais je préfère avoir tout en une seule clé.

J'ai regardé les transformations web.config disponibles mais rien ne semble être orienté vers ce que j'essaie d'accomplir.

Voici les sites web que j'utilise comme référence :

Le blog de Vishal Joshi , Aide MSDN et Vidéo de Channel9

Toute aide serait très appréciée !

-D

70voto

Sayed Ibrahim Hashimi Points 25707

En fait, vous pouvez le faire, mais ce n'est pas aussi facile que vous le pensez. Vous pouvez créer votre propre transformation de configuration. Je viens d'écrire un article de blog très détaillé à l'adresse suivante http://sedodream.com/2010/09/09/ExtendingXMLWebconfigConfigTransformation.aspx à ce sujet. Mais voici les points saillants :

  • Créer un projet de bibliothèque de classe
  • Référence Web.Publishing.Tasks.dll (sous %Program Files (x86)%MSBuild \Microsoft\VisualStudio\v10.0\Web dossier)
  • Étendre la classe Microsoft.Web.Publishing.Tasks.Transform.
  • Mettre en œuvre la méthode Apply()
  • Placez l'assemblage dans un endroit bien connu
  • Utilisez xdt:Import pour rendre la nouvelle transformation disponible.
  • Utiliser la transformation

Voici la classe que j'ai créée pour faire ce remplacement

namespace CustomTransformType
{
    using System;
    using System.Text.RegularExpressions;
    using System.Xml;
    using Microsoft.Web.Publishing.Tasks;

    public class AttributeRegexReplace : Transform
    {
        private string pattern;
        private string replacement;
        private string attributeName;

        protected string AttributeName
        {
            get
            {
                if (this.attributeName == null)
                {
                    this.attributeName = this.GetArgumentValue("Attribute");
                }
                return this.attributeName;
            }
        }
        protected string Pattern
        {
            get
            {
                if (this.pattern == null)
                {
                    this.pattern = this.GetArgumentValue("Pattern");
                }

                return pattern;
            }
        }

        protected string Replacement
        {
            get
            {
                if (this.replacement == null)
                {
                    this.replacement = this.GetArgumentValue("Replacement");
                }

                return replacement;
            }
        }

        protected string GetArgumentValue(string name)
        {
            // this extracts a value from the arguments provided
            if (string.IsNullOrWhiteSpace(name)) 
            { throw new ArgumentNullException("name"); }

            string result = null;
            if (this.Arguments != null && this.Arguments.Count > 0)
            {
                foreach (string arg in this.Arguments)
                {
                    if (!string.IsNullOrWhiteSpace(arg))
                    {
                        string trimmedArg = arg.Trim();
                        if (trimmedArg.ToUpperInvariant().StartsWith(name.ToUpperInvariant()))
                        {
                            int start = arg.IndexOf('\'');
                            int last = arg.LastIndexOf('\'');
                            if (start <= 0 || last <= 0 || last <= 0)
                            {
                                throw new ArgumentException("Expected two ['] characters");
                            }

                            string value = trimmedArg.Substring(start, last - start);
                            if (value != null)
                            {
                                // remove any leading or trailing '
                                value = value.Trim().TrimStart('\'').TrimStart('\'');
                            }
                            result = value;
                        }
                    }
                }
            }
            return result;
        }

        protected override void Apply()
        {
            foreach (XmlAttribute att in this.TargetNode.Attributes)
            {
                if (string.Compare(att.Name, this.AttributeName, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    // get current value, perform the Regex
                    att.Value = Regex.Replace(att.Value, this.Pattern, this.Replacement);
                }
            }
        }
    }
}

Voici le web.config

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="one" value="one"/>
    <add key="two" value="partial-replace-here-end"/>
    <add key="three" value="three here"/>
  </appSettings>
</configuration>

Voici mon fichier de transformation config

<?xml version="1.0"?>

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <xdt:Import path="C:\Program Files (x86)\MSBuild\Custom\CustomTransformType.dll"
              namespace="CustomTransformType" />

  <appSettings>
    <add key="one" value="one-replaced" 
         xdt:Transform="Replace" 
         xdt:Locator="Match(key)" />
    <add key="two" value="two-replaced" 
         xdt:Transform="AttributeRegexReplace(Attribute='value', Pattern='here',Replacement='REPLACED')" 
         xdt:Locator="Match(key)"/>
  </appSettings>
</configuration>

Voici le résultat après transformation

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="one" value="one-replaced"/>
    <add key="two" value="partial-replace-REPLACED-end"/>
    <add key="three" value="three here"/>
  </appSettings>
</configuration>

3voto

Juste une mise à jour, si vous utilisez Visual Studio 2013, vous devez référencer %Program Files (x86)%MSBuild \Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.XmlTransform.dll à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X