我一直在寻找正确的方法来确保在构建项目时将appsettings.json复制到bin目录中。
This article建议使用“无更新”
<ItemGroup>
<None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
并且this stackoverflow answer建议使用“无包含”:
<ItemGroup>
<None Include="appsettings.json" CopyToOutputDirectory="Always" />
</ItemGroup>
update
和include
有什么区别?
答案 0 :(得分:1)
更新和包含有什么区别?
用法:
Include
属性=>要包含在项目列表中的文件或通配符。
Update
属性=>使您能够修改使用glob包含的文件的元数据。
工作范围:
Include attribute
:
1。适用于normal .net framewrok
(非SDK格式),.net core and .net standard
(SDK格式)以及C ++项目...
2。用于许多VS版本(据我所知,从VS2010到VS2019)
3。Include
即使在Targets中的ItemGroup中也有效
Update attribute
:
1.Works for .net核心项目
2。在VS2017及更高版本中可用
3。在目标内的ItemGroup中使用它时不支持
测试和结果:
不包含c.txt时进行首次测试:
<ItemGroup>
<DoSth Include="a.txt"/>
<DoSth Include="b.txt"/>
<DoSth Update="c.txt" Metadata="test"/>
</ItemGroup>
<Target Name="MyTest" AfterTargets="build">
<Message Text="@(DoSth)" Importance="high"/>
</Target>
<!--The output is a.txt and b.txt, no c.txt.-->
包含c.txt的第二次测试:
<ItemGroup>
<DoSth Include="a.txt"/>
<DoSth Include="b.txt"/>
<DoSth Include="c.txt" Metadata="original"/>
<DoSth Update="c.txt" Metadata="test"/>
</ItemGroup>
<Target Name="MyTest" AfterTargets="build">
<Message Text="@(DoSth)" Importance="high"/> <!--The output files are a.txt,b.txt and c.txt.-->
<Message Text="%(DoSth.Identity)+%(DoSth.Metadata)" Importance="high"/> <!--The output Metadata of c.txt is test instead of original-->
</Target>
因此,很明显Update attribute
仅用于更新一个项目的元数据。它没有包含某些文件的功能。而且只有在一个项目中包含一个文件时,它才起作用。
要澄清在
Update + appsettings.json
控制台中使用.net core
时的某些情况,asp.net core
网络应用程序:
在Asp.net核心Web应用程序中:
如果您创建一个新的asp.net core web
项目,则默认情况下可以在解决方案资源管理器中看到appsettings.json
文件。但是,如果您阅读了xx.csproj
,则无法在其中找到定义,对于{sdk格式,xx.csproj
中没有明确显示定义。
在这种情况下,如果我们使用诸如<None Include="appsettings.json" CopyToOutputDirectory="Always" />
之类的脚本,则始终可以将该文件复制到输出。
但是对于脚本<None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
,它仅在项目文件中没有像<Content xxx="appsettings.json"...>
这样的语句时才起作用。
我建议您通过VS UI进行操作,而不要手动编辑xx.csproj。我们可以在Build Action and Copy To Output
中更改Property Window
的设置:
如果将build action
设置为None
,将“复制到输出”设置为Copy if Never
中的Copy Always
,则在xx.csproj中,我们可以找到:
<ItemGroup>
<Content Remove="appsettings.json" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
因此,VS为此使用了None + Include。综上所述,我建议您在项目中使用None+Include
而不是None+Update
。另外,最推荐的方法是在VS IDE中通过UI控制复制行为,而不是手动编辑。希望以上所有对您有所帮助:)
更新1:
我们可以将此脚本添加到项目文件中,以输出有关csproj中未显示的None Items和Content Items的信息:
<Target Name="TrytoFindDefinitionsNowShown" AfterTargets="build">
<Message Text="None: @(None)" Importance="high"/>
<Message Text="Content: @(Content)" Importance="high"/>
</Target>
Update2:
我只是做了一些测试,甚至在VS中的.net核心控制台项目中也找到了,尽管csproj中没有定义,但该更新可以正常进行。奇怪?
最后我发现这是因为该定义在csproj文件中被隐藏或未显示,实际上,当您在项目中有一个appsettings.json文件时,您已经有一个{{1} }定义(有时Content + include,ikt取决于您添加该文件的方式),尽管在csproj中看不到,但请参见我的屏幕截图:
所以这就是为什么Update可以用于复制行为的原因,尽管它用于修改元数据。在使用更新之前,虽然csproj中没有显示定义<None Include="appsettings.json"...
,但已经存在。 (对于sdk格式)
Update3:
我对Update1中的脚本做了一些小的更改,以显示None+Include+Appsettings.json
的元数据。
因此,在.net核心控制台项目中,<None Include="appsettings.json">
文件默认为
appsettings.json
这就是<None Include="appsettings.json" CopyToOutputDirectory="Never" />
(覆盖)和None+Include+Always
(修改元数据)都可以实现复制行为的原因。它可以说明为什么默认情况下即使VS在某个地方隐藏了None+Update+Always or PreserveNewest
定义也不会复制该文件。因为默认情况下None+Include
设置为“从不”。