Web Config Transform이 작동하지 않음


88

.NET MVC 3.0 응용 프로그램에서 다음 구성이 있습니다 appSettings.

web.config

<appSettings>
<add key="SMTPHost" value="mail.domain.com"/>
    <add key="SMTPUsername" value="user@gmail.com"/>
    <add key="SMTPPort" value="25"/>
    <add key="SMTPPwd" value="mypassword"/>
    <add key="EmailFrom" value="notific@gmail.com"/>
</appSettings>

디버깅을 위해 다음 구성 변환이 정의되어 있습니다.

web.Debug.config

<appSettings>
    <add  key="SMTPPort" value="58" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>

그리고 디버그 모드에서 응용 프로그램을 실행,하지만 내 SMTP 포트는 여전히에서 값을 복용 web.config하지 web.Debug.config.

누구든지이 구성에서 무엇이 잘못되었을 수 있는지 제안 할 수 있습니까?

답변:


156

Web.config 변환은 게시 작업의 일부로 만 적용됩니다.

당신이이의 일환으로 수행하려면 app.config: XML의 변환 비주얼 스튜디오 플러그인 - 빌드 작업, 당신은 SlowCheetah을 사용할 수 있습니다

http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5


1
시간을 많이 절약 해주셔서 감사합니다.
HaBo

3
와우이 답변을 찾는 데 2 ​​시간이 걸렸습니다. 게시 해주셔서 감사합니다.
Peanut

Visual Studio 2015 (웹)에서 .config 변환 은 이제 기본 제공 기능이므로 더 이상 SlowCheetah가 필요하지 않습니다. 그러나 기본 제공 변환은 애플리케이션을 실행하는 경우가 아니라 게시하는 경우에만 적용됩니다. 내가 어떻게 해결했는지 여기에서 볼 수 있습니다 .
매트

1
@komsky의 답변이 간단하고 깨끗한 솔루션을 제공하는 동안 왜 이것을 사용 해야하는지 잘 모르겠습니다.
Csaba Toth

2
SlowCheetah는 훌륭하지만 자체 문서에서 "웹 프로젝트의 경우 애플리케이션을 게시하거나 패키징 할 때 파일이 변형됩니다." 즉, 디버깅 중이 아닙니다.
Doug

32

Visual Studio (2010-2019) 는 불행히도 디버깅하는 동안 직접 지원 하지 않으며 게시 전용입니다. web.config).

참고 이 있음을 해결 CodeProject의에 설명 .

현재 web.config를 변환 된 버전으로 덮어 쓰도록 .msproj 파일을 수정하는 방법을 설명합니다.

먼저 해당 해결 방법을 옵션 1 로 설명 하지만 최근 에 사용하기 더 쉬운 다른 옵션 2를 발견했습니다 (원하는 경우 옵션 2로 직접 스크롤 할 수 있음).


옵션 1 : 원본 코드 프로젝트 문서 (위 링크 참조) 에서 가져온 지침을 추가했습니다 . 스크린 샷이 이미 사라졌기 때문에 전체 정보를 잃고 싶지 않기 때문입니다.

VS.Net은 로컬 환경을 개발하고 디버깅 할 때 변환을 수행하지 않습니다. 그러나 원하는 경우이를 수행하기 위해 수행 할 수있는 몇 가지 단계가 있습니다.

  • 먼저 기본 디버그 및 릴리스가 수행하려는 작업에 충분하지 않다고 가정하고 VS.Net 에서 원하는 구성을 만듭니다 .
  • 사용자를 마우스 오른쪽 버튼으로 클릭하고 구성 변환 추가를web.config 선택 하면 정의 된 각 구성에 대한 종속 변환 구성이 생성됩니다.
  • 이제 이름 web.configweb.base.config.
  • web.config프로젝트에를 추가 하십시오. 빌드를 수행 할 때마다 덮어 쓰여지기 때문에 그 안에있는 내용은 중요하지 않지만 프로젝트의 일부를 원하므로 VS.Net"당신의 프로젝트가 디버깅을 위해 구성되지 않았습니다"라는 팝업을 표시 하지 않습니다. 쪽으로.
  • .csproj프로젝트 파일을 편집 TransformXml하고 AfterBuild 대상에 다음 작업을 추가합니다 . 여기 내가 변화 될 것입니다 볼 수 있습니다 web.base.config을 사용하여 파일을 web.[configuration].config그리고로 저장됩니다 web.config. 자세한 내용은 Microsoft Q & A 를 확인 하고 빌드를 확장하는 방법에 대한 지침은 여기를 참조하십시오 .

옵션 2 :

답변을 기반으로 간단한 콘솔 앱인 TransformConfig.exe (C # 6.0 구문)를 개발했습니다.

using System;
using System.Linq;
using Microsoft.Web.XmlTransform;

namespace TransformConfig
{

  class Program
  {
    static int Main(string[] args)
    {
        var myDocumentsFolder = $@"C:\Users\{Environment.UserName}\Documents";
        var myVsProjects = $@"{myDocumentsFolder}\Visual Studio 2015\Projects";

        string srcConfigFileName = "Web.config";
        string tgtConfigFileName = srcConfigFileName;
        string transformFileName = "Web.Debug.config";
        string basePath = myVsProjects + @"\";
        try
        {

            var numArgs = args?.Count() ?? 0;
            if (numArgs == 0 || args.Any(x=>x=="/?"))
            {
                Console.WriteLine("\nTransformConfig - Usage:");
                Console.WriteLine("\tTransformConfig.exe /d:tgtConfigFileName [/t:transformFileName [/s:srcConfigFileName][/b:basePath]]");
                Console.WriteLine($"\nIf 'basePath' is just a directory name, '{basePath}' is preceeded.");
                Console.WriteLine("\nTransformConfig - Example (inside PostBuild event):");
                Console.WriteLine("\t\"c:\\Tools\\TransformConfig.exe\"  /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:\"$(ProjectDir)\\\"");
                Environment.ExitCode = 1;
                return 1;
            }

            foreach (var a in args)
            {
                var param = a.Trim().Substring(3).TrimStart();
                switch (a.TrimStart().Substring(0,2).ToLowerInvariant())
                {
                    case "/d":
                        tgtConfigFileName = param ?? tgtConfigFileName;
                        break;
                    case "/t":
                        transformFileName = param ?? transformFileName;
                        break;
                    case "/b":
                        var isPath = (param ?? "").Contains("\\");
                        basePath = (isPath == false)
                                    ? $@"{myVsProjects}\" + param ?? ""
                                    : param;
                        break;
                    case "/s":
                        srcConfigFileName = param ?? srcConfigFileName;
                        break;
                    default:
                        break;
                }
            }
            basePath = System.IO.Path.GetFullPath(basePath);
            if (!basePath.EndsWith("\\")) basePath += "\\";
            if (tgtConfigFileName != srcConfigFileName)
            {
                System.IO.File.Copy(basePath + srcConfigFileName,
                                     basePath + tgtConfigFileName, true);
            }
            TransformConfig(basePath + tgtConfigFileName, basePath + transformFileName);
            Console.WriteLine($"TransformConfig - transformed '{basePath + tgtConfigFileName}' successfully using '{transformFileName}'.");
            Environment.ExitCode = 0;
            return 0;
        }
        catch (Exception ex)
        {
            var msg = $"{ex.Message}\nParameters:\n/d:{tgtConfigFileName}\n/t:{transformFileName}\n/s:{srcConfigFileName}\n/b:{basePath}";
            Console.WriteLine($"TransformConfig - Exception occurred: {msg}");
            Console.WriteLine($"TransformConfig - Processing aborted.");
            Environment.ExitCode = 2;
            return 2;
        }
    }

    public static void TransformConfig(string configFileName, string transformFileName)
    {
        var document = new XmlTransformableDocument();
        document.PreserveWhitespace = true;
        document.Load(configFileName);

        var transformation = new XmlTransformation(transformFileName);
        if (!transformation.Apply(document))
        {
            throw new Exception("Transformation Failed");
        }
        document.Save(configFileName);
    }

  }
}

DLL "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.XmlTransform.dll"을 참조로 추가해야합니다 (이 예는 VS 2015에 적용되며, 이전 버전의 v14.0경우 경로에서를 적절한 버전 번호 (예 :)로 바꿉니다 v11.0).

들어 비주얼 스튜디오 2017, 경로를 명명 스키마가 변경되었습니다 예를 들어, 엔터프라이즈 버전은 여기에 있습니다 : C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web.
전문가 버전의 Enterprise경우 경로에서 Professional. 미리보기 버전을 사용하는 경우 추가 2017Preview.

여기에 경로 (엔터프라이즈 버전이없는 경우 교체해야 할 수도 비주얼 스튜디오의 다른 버전을 변경하는 방법에 대한 개요입니다 Enterprise의해 Professional경로에) :

VS 버전         경로 (for Microsoft.Web.XmlTransform.dll)
2015                   C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web
2017                   C:\Program Files (x86)\Microsoft Visual Studio\2017\
                          Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
2019                  C:\Program Files (x86)\Microsoft Visual Studio\2019\
                          Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\Web

그것을 컴파일하고 .exe 파일을 디렉토리 (예 : C:\MyTools\.

사용법 : 빌드 후 이벤트 에서 사용할 수 있습니다 ( 프로젝트 속성 에서 빌드 이벤트 를 선택한 다음 빌드이벤트 명령 줄 편집 ). 명령 줄 매개 변수는 다음과 같습니다 (예제).

"C : \ MyTools \ TransformConfig.Exe"/d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config / b : "$ (ProjectDir) \"

즉, 먼저 구성 파일의 이름, 변환 구성 파일, 선택적 템플릿 구성, 두 파일이 모두 포함 된 프로젝트의 경로 순입니다.

선택 사항 인 템플릿 구성 매개 변수를 추가했습니다. 그렇지 않으면 원래의 전체 구성이 변환에 의해 덮어 쓰여지며, 이는 템플릿을 제공하여 피할 수 있습니다.

원본 Web.config를 복사하여 템플릿을 만들고 이름을 Web.Template.config로 지정합니다.

노트 :

  • 원하는 경우 TransformConfig.exe파일을 위에서 언급 한 Visual Studio 경로에 복사 Microsoft.Web.XmlTransform.dll하여 구성을 변환해야하는 모든 프로젝트에서 참조 할 수도 있습니다.

  • 내가 Environment.ExitCode = x;할당을 추가 한 이유를 궁금해하는 분들을 위해 : Main에서 단순히 int를 반환하는 것은 빌드 이벤트에 도움이되지 않았습니다. 자세한 내용은 여기를 참조 하세요.

  • 프로젝트를 게시하고 Web.Template.config를 사용하는 경우 게시하기 전에 올바른 구성 (일반적으로 릴리스)으로 솔루션을 다시 빌드 했는지 확인합니다 . 그 이유는 디버깅 중에 Web.Config를 덮어 쓰고 그렇지 않으면 잘못된 파일을 변환 할 수 있기 때문입니다.


1
CodeProject 게시물이 멍청한 것 같습니다. 그는 코드 샘플에 스크린 샷을 사용했으며 이제 블로그가 다운 되었기 때문에 기록에 손실되었습니다.
Eric Lloyd

3
예, 안타깝게도 스크린 샷이 사라졌습니다. 그러나 적어도 기사 텍스트는 여전히 거기에 있으며 접근 방식을 설명합니다. 나는 그것을 잃지 않도록 내 대답에 텍스트 설명을 추가했습니다.
Matt

1
사실, 아마도 codeproject의 저자 James Coleman에게 연락하여 문제를 해결할 수 있습니다. 그래도 그가 여전히 활동 중인지 확실하지 않습니다. @ThomasTeilmann
Matt

잃어버린 스크린 샷에 있던 것과 비슷할 것 같습니다. 동일한 기본 결과를 달성하는 것 같습니다. stackoverflow.com/a/6437192/1003916
user1003916

22

Web.config를 Web.debug.config로 변환하려는 경우-변환 효과를 저장해야하는 위치에 문제가 있으므로 질문에 대답하는 것은 간단하지 않습니다. Web.config 자체에서? 이것은 변환 소스 파일을 덮어 씁니다! 아마도 이것이 Visual Studio가 빌드 중에 변환을 수행하지 않는 이유 일 것입니다.

이전 Matt 답변은 유효하지만 디버그에서 릴리스 등으로 활성 솔루션 구성을 실제로 변경할 때 작동하는 일반 솔루션을 갖도록 혼합 할 수 있습니다. 다음은 간단한 솔루션입니다.

  1. 구성 (디버그, 릴리스 등)에 대한 구성 변환 생성
  2. Web.config파일 이름을 다음 Web.base.config으로 변경-변형은 그에 따라 자동으로 이름을 변경해야합니다 ( Web.base.Debug.config등).
  3. 프로젝트 폴더에 다음 transformWebConfig.proj XML 파일 을 추가 합니다.
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="TransformWebConfig" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="TransformWebConfig">
    <TransformXml Source="Web.base.config" Transform="Web.base.$(CurrentConfig).config" Destination="Web.config" />
  </Target>
</Project>
  1. 프로젝트 속성으로 이동하여 빌드 이벤트를 선택하고 빌드 후 이벤트 명령 줄 에 다음 콘텐츠를 추가 합니다 .
@if exist "%ProgramFiles(x86)%\MSBuild\12.0\bin" set PATH=%ProgramFiles(x86)%\MSBuild\12.0\bin;%PATH%
msbuild $(ProjectDir)transformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath)

이제 솔루션을 빌드 할 때 활성 구성에 대한 유효한 변환이 포함 된 Web.config 파일이 생성됩니다.


깨끗하고 최고의 답변. 몇 가지 질문 : 1. XML 유효성 검사에서 TransformXml 요소가 Target 요소 내에서 유효하지 않다고 말하는 이유는 무엇입니까? (빌드는 BTW에서 작동합니다). 2. 이제 실제 Web.Config가 생성되었으므로 Web.Config를 프로젝트에 추가합니다. 이제 디버그 / 릴리스 사이를 전환 할 때마다 web.config가 변경되지만 항상 소스 저장소에 커밋하고 싶지는 않습니다.
Csaba Toth

1. VS가 스키마를 사용하여이 XML의 유효성을 검사하는 방법을 말할 수는 없지만이 경고는 일반적이므로 무시할 수 있습니다. 2. 사용중인 저장소에 따라 다르지만 예를 들어 git.ignore 파일 항목을 사용할 수 있습니다.
komsky

4
이것은 나를 위해 잘 작동했습니다. 빌드 이벤트 및 proj 파일의 12를 현재 버전으로 변경했습니다. 빌드 후 이벤트의 경우 다음을 사용 하고 .proj 파일에서 '"$(MSBuildBinPath)\msbuild.exe" $(ProjectDir)TransformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath) 업데이트 v12.0했습니다 v14.0.
Jovie apr

1
VS 2017는 모든 수정의 경우 12.014.0
사바 토스

1
1) 생성 된 web.config를 웹 프로젝트에 포함하는 것을 잊지 마십시오. 그렇지 않으면 게시 된 후 대상 폴더에 복사되지 않습니다. 2) 빌드 서버에이 두 파일이없는 경우 "Microsoft.Web.Publishing.Tasks", "Microsoft.Web.XmlTransform"서버에 복사하십시오
phiree

8

VS 2017를 위해 나는 답을 찾을 여기 아무도는 매우 인기있는 솔루션으로 나타나는 위를 참조 없다 왜 확인합니다. 너무 쉽습니다. 2019 년 3 월 5 일 IOrlandoni가 VS 2017 및 모든 버전에서 작동하도록 만든 댓글을 확인하세요.

기본적으로 두 스테퍼입니다. 먼저 .csproj 파일을 편집하고 아래 코드를 추가합니다. 둘째, 새 web.base.config 구성을 만들고 여기에 기존 web.config를 복사합니다. 그런 다음 모든 빌드가 원하는 변환으로 web.config를 덮어 씁니다.

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
    <TransformXml Source="Web.Base.config" 
        Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>  

이것은 아마도 최선의 대답이지만 IMO에는 트릭이 없습니다. Web.config에서 Content로 변경 None하면 사용할 수 있습니다 Source="Web.config" Destination="$(TargetPath).config"(또는 일부 유형의 프로젝트에 대해 Destination="$(TargetDir)Web.config"). 또한 AfterBuild파일을 복사하기 전에 더 이상 수행 할 필요가 없기 때문에 변환을로 옮겼습니다 .
Peter Taylor 19

좋아, 실제로 작동하지 않습니다. 어떤 이유로에서 실행하도록 구성 할 수 없기 때문입니다 bin.
Peter Taylor 19

5

귀하의 즉각적인 질문에 대한 답변이 있습니다. 설명은 변환이 빌드가 아닌 게시시 적용된다는 것입니다.

하지만 원하는 것을 달성하는 방법에 대한 솔루션을 제공하지 않는다고 생각합니다.

나는 web.config를 깨끗하게 유지하고 각 변환 파일의 환경에 따라 달라지는 모든 키를 설정하는 방법을 찾기 위해 며칠 동안이 정확한 문제로 고심하고 있습니다. 내 결론은 가장 쉽고 안정적인 솔루션은 원본 web.config에서 디버그 값을 사용하는 것입니다. 이렇게하면 Visual Studio에서 디버그를 실행할 때 항상 표시됩니다.

그런 다음 게시하려는 다양한 환경 (테스트, 통합, 프로덕션)에 대한 변환을 생성합니다. 게시 할 때 web.config 파일을 변환하는 기본 제공 기능으로 충분합니다. SlowCheetah 또는 빌드 이벤트 또는 프로젝트 파일 편집이 필요하지 않습니다. 웹 프로젝트 만있는 경우.

원하는 경우 개발 환경과 관련된 모든 값이 포함 된 별도의 파일을 유지하기 위해 솔루션에 web.debug.config 파일을 포함 할 수도 있습니다. 다른 사람이 해당 목적으로 사용하려고 할 경우를 대비하여 Visual Studio에서 실행할 때 값이 적용되지 않는다는 주석을 달아야합니다!


1

사용 문어 배포 (커뮤니티 에디션은 무료입니다) 그리고 그것은 변환 할 web.config당신을 위해. 단계 :

  1. 웹 애플리케이션 배포를위한 Octopus 설정
  2. 있는지 확인은 Web.Release.configBuild Action에 속성 집합 Content단지 주와 같은 web.config파일을.

그게 다야! Octopus는 특별한 구성없이 나머지 작업을 수행합니다. 기본 IIS 웹 사이트 배포는이 작업을 즉시 수행합니다.여기에 이미지 설명 입력


번호 2 : 열쇠
레자


0

최근 에 .NET Framework 2.0을 기반으로 한 이전 web.config 파일 에서 동일한 문제가 발생했습니다 . 해결책은 단순히 web.config의 네임 스페이스 ( 구성 루트 노드의 xmlns attibute)를 제거하는 것입니다 .

전에: <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

후: <configuration>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.