40

¿Alguien sabe si hay una forma de "transformar" secciones específicas de valores en lugar de reemplazar el valor completo o un atributo?Tareas avanzadas utilizando la transformación Web.Config

Por ejemplo, tengo varias entradas de AppSettings que especifican las URL para diferentes servicios web. Estas entradas son ligeramente diferentes en el entorno de desarrollo que en el entorno de producción. Algunos son menos trivial que otros

<!-- 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> 

en cuenta que una entrada en el puño, la única diferencia es ".dev" de ".prod". En la segunda entrada, el subdominio es diferente: "MA1-lab.lab1" de "ws.ServiceName2"

Hasta ahora, sé que puedo hacer algo como esto en el 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" /> 

Sin embargo, cada vez que la versión para ese servicio web se actualiza, tendría que actualizar el Web.Release.Config, así, que contradice el objetivo de simplfying mis actualizaciones web.config.

Sé que también podría dividir esa URL en diferentes secciones y actualizarlas de forma independiente, pero prefiero tenerlo todo en una clave.

He revisado la web.config disponible Transformaciones pero nada parece estar orientado hacia lo que intento lograr.

Estos son los sitios web que estoy usando como referencia:

Vishal Joshi's blog, MSDN Help y Channel9 video

Cualquier ayuda sería muy apreciada!

-D

Respuesta

66

Como cuestión de hecho, usted puede hacer esto, pero no es tan fácil como se podría pensar. Puede crear su propia transformación de configuración. Acabo de escribir una publicación de blog muy detallada en http://sedodream.com/2010/09/09/ExtendingXMLWebconfigConfigTransformation.aspx con respecto a esto. Pero aquí están los destacar:

  • Crear proyecto de biblioteca de clases
  • Referencia Web.Publishing.Tasks.dll (en% Archivos de programa (x86)% MSBuild \ Microsoft \ VisualStudio \ carpeta v10.0 \ Web)
  • Extender la clase Microsoft.Web.Publishing.Tasks.Transform
  • Implementar el método Aplicar()
  • Coloque el conjunto en un lugar bien conocido
  • uso xdt: Importar para hacer la nueva trans formulario disponible
  • Uso transformar

Aquí está la clase que he creado para hacer esto reemplazar

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); 
       } 
      } 
     } 
    } 
} 

Aquí está 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> 

Aquí está mi config archivo de transformación

<?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> 

aquí está el resultado después de la transformación

<?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> 
+0

Sayed, ¡esto es asombroso! muchas gracias por tomarse el tiempo para responder a esto, estaba empezando a perder la esperanza :) –

+0

Santo creeps, ¡esto es IMPRESIONANTE! Muchas gracias, amigo ... esto es exactamente lo que necesito :) –

+0

Es tan horrible que no hay una manera más simple de hacer esto. :(Gracias por esto, sin embargo, fue muy útil. –

3

Así como una actualización, si se está utilizando Visual Studio 2013 , en su lugar, debe hacer referencia a% Archivos de programa (x86)% MSBuild \ Microsoft \ VisualStudio \ v12.0 \ Web \ Microsoft.Web.XmlTransform.dll.

Cuestiones relacionadas