6

I currently have a solution with a web.api project that I want to deploy to different virtual directories in my local IIS. Currently I am doing the following in the .csproj of the api:

<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)' == 'CustomerOne.Debug'">
    <CustomerName>CustomerOne</CustomerName>
    ....
</PropertyGroup>
...

These variables are used extenisvely further on for web.config transforms, copying to different locations, etc., by referencing them like $(CustomerName).

The only place where it does not work is in the definition of the virtual directory, i.e., I'd like to connect the build configuration to the IISUrl below, which you can hardcode:

<ProjectExtensions>
  <VisualStudio>
    <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
      <WebProjectProperties>
        ...
        <IISUrl>http://localhost/api/something</IISUrl>
        ...
      </WebProjectProperties>
    </FlavorProperties>
  </VisualStudio>
</ProjectExtensions>

Replacing this by <IISUrl>http://localhost/api/$(CustomerName)</IISUrl> does not work. Ideas?

EluciusFTW
  • 2,565
  • 6
  • 42
  • 59
  • To clarify: Leo Lui-MSFTs answer has already answered _why_ it does not work. I am interested in _how to_ get it to work, i.e., how to configure the IISUrl depending on build configuration. – EluciusFTW Jan 10 '19 at 09:45
  • Sounds is similar to an issue I encountered in the past. Have a look at the solution provided by [this answer](https://stackoverflow.com/a/12409127/419761). The idea is to use `DefineConstants`. – l33t Jan 15 '19 at 15:24

2 Answers2

2

Replacing this by http://localhost/api/$(CustomerName) does not work. Ideas?

That because Anything inside of a ProjectExtensions element will be ignored by MSBuild.

You can get the detailed info from this document ProjectExtensions Element (MSBuild):

Allows MSBuild project files to contain non-MSBuild information. Anything inside of a ProjectExtensions element will be ignored by MSBuild.

That is the reason why the Msbuild variables not work in Project Extensions.

Hope this helps.

Leo Liu
  • 71,098
  • 10
  • 114
  • 135
  • Thanks for that information. However you did not propose a solution on how to make that work, i.e., how to set the virtual directory dynamically. – EluciusFTW Jan 10 '19 at 09:13
  • @EluciusFTW, Oh, sorry, I see your question is why it doesn't work, not how to solve it. I thought you didn't care about the solution, so I didn't provide a solution. How about use the condition on the ``, like ``, then set the static path in the IISUrl, and add another condition with another static path in the IISUrl. You can test it if it works for you. – Leo Liu Jan 10 '19 at 09:34
  • Thanks again, I'll definitely try that. But it would not be ideal as I have 20ish build configurations. – EluciusFTW Jan 10 '19 at 09:35
  • @Leu Lui-MSFT Unfortunately it does not work: "The attribute Condition in element is unrecognized". – EluciusFTW Jan 10 '19 at 09:42
  • @EluciusFTW, Yes, I test it just now and got the same result. So the Msbuild variables could not use onthe ProjectExtensions element and inside it. I will continue to investigate it to see if there is any solution. If I get any update, I will let you know. – Leo Liu Jan 10 '19 at 09:55
1

You could update the underlying project file. A Target like this in your project file would do it.

  <Target Name="AfterBuild">
    <PropertyGroup>
      <NewUrl>http://localhost/api/$(CustomerName)</NewUrl>
    </PropertyGroup>
    <Message Text="Updating IISUrl: $(NewUrl) in $(MSBuildProjectFile)" />
    <XmlPeek Namespaces="&lt;Namespace Prefix='msb' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/&gt;" XmlInputPath="$(MSBuildProjectFile)" Query="/msb:Project/msb:ProjectExtensions/msb:VisualStudio/msb:FlavorProperties/msb:WebProjectProperties/msb:IISUrl/text()">
      <Output TaskParameter="Result" ItemName="Peeked" />
    </XmlPeek>
    <Message Text="Current Url: @(Peeked)" />
    <!-- Only update the IISUrl if its changed -->
    <XmlPoke Condition=" '@(Peeked)'!='$(NewUrl)' " XmlInputPath="$(MSBuildProjectFile)" Namespaces="&lt;Namespace Prefix='msb' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/&gt;" Query="/msb:Project/msb:ProjectExtensions/msb:VisualStudio/msb:FlavorProperties/msb:WebProjectProperties/msb:IISUrl" Value="$(NewUrl)" />
  </Target>

However it does have side affects. Changing the underlying project file means Visual Studio decides it should reload the project.

To use it you cannot go directly into Debug. Instead build, reload the project and then go into debug. If you go directly into Debug (with a compile) it will use the old url.

PhilS
  • 624
  • 3
  • 5
  • Since my bounty is ending, and this is the only real solution I will award it to this answer. Even though it seems like an absolute use-case, maybe there issimply no better solution than editing the .csproj via a script like this :/ – EluciusFTW Jan 20 '19 at 21:15