Templating: Document how to escape a Condition

Created on 28 Feb 2018  路  12Comments  路  Source: dotnet/templating

Back in the .NET Core 1.1 release I was able to do this in my csproj to conditionally add things:

<Project Sdk="Microsoft.NET.Sdk.Web">
<!--#if (AuthoringMode)-->
  <PropertyGroup>
    <DefineConstants>$(DefineConstants);Swagger</DefineConstants>
  </PropertyGroup>
  <ItemGroup>
    <Content Include=".template.config\**\*" />
  </ItemGroup>
  <!--#endif-->

<ItemGroup Label="Package References">
    <PackageReference Include="Boilerplate.AspNetCore.Swagger" Version="3.0.0" Condition="'$(Swagger)' == 'true'" />
</ItemGroup>
</Project>

The Condition="'$(Swagger)' == 'true'" syntax gives compile time errors in .NET Core 2.0. I discovered somewhere that I can use the following syntaxinstead:

<PackageReference Include="Boilerplate.AspNetCore.Swagger" Version="3.0.0" Condition="$(DefineConstants.Contains('Swagger'))" />

This syntax compiles but no longer works with dotnet new. Is there a solution to this problem? Should I also be using #if comment syntax like this:

<!--#if (Swagger)-->
<PackageReference Include="Boilerplate.AspNetCore.Swagger" Version="3.0.0" Condition="$(DefineConstants.Contains('Swagger'))" />
<!--#endif-->
2.0 triaged

All 12 comments

@RehanSaeed

[original comment removed]

Update:
(I realized an error in how I was testing this)
Could you provide the specific error you're getting? Also, is this error from trying to build/run the template source, or from trying to build/run an invocation of the template created via dotnet new?

@RehanSaeed - could you also provide the definition of your swagger symbol in the template.json ? Or if you can point me at a public repo containing this template version, I can take a look directly.

Workaround

I've switched to using the comment syntax to work around this problem. This works but has the downside of not adding/removing the package based on the constants I define.

<!--#if (Swagger)-->
<PackageReference Include="Boilerplate.AspNetCore.Swagger" Version="3.0.0" />
<!--#endif-->

Can't Build Template Project

<PackageReference Include="Boilerplate.AspNetCore.Swagger" 
    Version="3.0.0" 
    Condition="'$(Swagger)' == 'true'" />

The Condition="'$(Swagger)' == 'true'" syntax does work when creating a project from the template but using it means that the template project no longer builds. The error it gives is:

error CS0234: The type or namespace name 'Swagger' does not exist in the namespace 'Boilerplate.AspNetCore' (are you missing an assembly reference?)

This suggests that the project reference has not been added.

The New 'Correct' Condition Syntax

This syntax allows the template project to build but the templating engine no longer works. The package reference and condition are output to the project as is.

<PackageReference Include="Boilerplate.AspNetCore.Swagger" 
    Version="3.0.0" 
    Condition="$(DefineConstants.Contains('Swagger'))" />

Ah, I think I see what's going on here. Adding a Swagger property with a value of true to the AuthoringMode section should get the Condition="'$(Swagger)' == 'true'" syntax to work when building from template source and when generating from the template. We'll also take a look at adding support for the Contains operator, but that likely won't land until after the 2.1.0 .NET Core release.

<Project Sdk="Microsoft.NET.Sdk.Web">
<!--#if (AuthoringMode)-->
  <PropertyGroup>
    <DefineConstants>$(DefineConstants);Swagger</DefineConstants>
    <Swagger>true</Swagger>
  </PropertyGroup>
  <ItemGroup>
    <Content Include=".template.config\**\*" />
  </ItemGroup>
  <!--#endif-->

That seems to work. Looks like something has fundamentally changed in the way csproj defines constants.

Can we use Choose element?

how does one do the opposite, i.e. Condition="$(!DefineConstants.Contains('Swagger'))" throws an error - I am not sure what the parser is for these conditions, is there another format that would work?

Another question I have is how to escape a Condition, so that it gets output in the final project instead of resolved and then removed. For example, lets say I have this in my .csproj:

<PropertyGroup Label="Signing">
    <PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
</PropertyGroup>

How do I get the exact output above to be created in my project? The Condition always gets removed and I end up with this:

<PropertyGroup Label="Signing">
</PropertyGroup>
  1. Adding item to specific project corresponding to a targeted delivery area
  2. Once this has been done for the entire backlog, the next steps will be to prioritize within each project & output a delivery roadmap.
  3. At that point, the issues will be assigned to a corresponding milestone
  4. The team will then begin to deliver against the road map, contributions always welcome

@RehanSaeed, the solution how to escape the conditions is documented in another issue, please check if it solves the issue.
I will add this information to wiki article, so it is available for anyone interested.

@RehanSaeed I see PR #2527 but it is not yet merged, why was this issue closed early?

Closing item - the wiki article was updated.

Was this page helpful?
0 / 5 - 0 ratings