有没有办法自动将内容文件包含到asp.net项目文件中?

Mar*_*rko 78 asp.net msbuild csproj

我经常在我的ASP.NET项目中添加很多内容文件(主要是图像和js).我正在使用VS发布系统,在发布之前,新文件在我将它们包含在项目中之前不会发布.我想自动包含指定目录中的所有文件.有没有办法指定哪些目录应该自动包含在csproj文件中或其他地方?

Chr*_*ris 128

老线程,我知道,但我找到了一种方法来做到这一点,我一直忘记,并在我的搜索最后一次找到它,我偶然发现了这个问题.我发现的最好的方法是在.csproj文件中使用BeforeBuild目标.

<Target Name="BeforeBuild">
    <ItemGroup>
        <Content Include="**\*.less" />
    </ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)

VS 2010不会触及此部分,它确保每次构建项目时都将文件作为内容包含在内.

  • 至少在VS 2012中,只要您从项目中添加/删除文件并保存,不幸的是,这会扩展到完整列表.:( (4认同)
  • .less文件是要由Less CSS预处理器解析的css文件.谷歌"少点"获取更多信息.表达式"**\*.less"表示包含所有目录中的所有*.less文件.在MSBUILD中,**表示'所有目录递归' (3认同)
  • 只有在将BeforeBuild更改为AfterBuild之后,这才适用于我的情况,我的构建启动了一个移动文件的powershell脚本,然后我的azure web部署尝试无法获取,因为它们仅在构建成功后才存在.看到"BeforeBuild"让我知道可能还有一个"AterBuild".希望这有助于其他人. (3认同)
  • 根本不适合我.VS2015 (3认同)

Fil*_*urt 50

您只需扩展您的网站.csproj文件即可.只需使用递归通配符添加内容根文件夹:

...
<ItemGroup>
    <!-- your normal project content -->
    <Content Include="Default.aspx" />

    <!-- your static content you like to publish -->
    <Content Include="Images\**\*.*" />
</ItemGroup>
...
Run Code Online (Sandbox Code Playgroud)

这样做可以使您的解决方案浏览器中显示此文件夹和所有内容.

如果您尝试通过指定隐藏解决方案浏览器中的文件夹

<Content Include="Images\**.*.*">
    <Visible>false</Visible>
</Content>
Run Code Online (Sandbox Code Playgroud)

它不会被发表.


更新

正如您已经发现的那样,只要触摸解决方案中的文件夹,就会替换通配符,因为VS项目不是为了包含任意内容而设计的.

所以你必须确保文件夹及其内容永远不会在VS中修改 - 添加或删除文件只能在文件系统上完成...这就是你理解你的问题所需要的.

如果文件夹可以隐藏在VS中会更容易,但我找不到隐藏它和发布的方法.

另一种不成功的方法是通过CreateItemTask 包含该文件夹.这导致文件夹的内容发布到\ bin\app.publish\...并且无法说服它与.csproj中的内容项一起发布,所以我没有在我的答案中显示它.

  • 它一直有效,直到我手动添加或删除文件.在该行之后<Content Include ="Images\**\*.*"/>从项目文件中消失. (3认同)
  • @Marko是对的.添加`<Content Include ="Images\**\*.*"/>`之后就可以了.一旦你添加了更多的图像,.csproj就会被更改,并返回列出images/...中的所有文件,而<Content Include ="Images\**\*.*"/>就不见了. (2认同)

Jes*_*sse 15

对于那些使用Chris回答问题的人来说,这是Visual Studio 2012及更新版本的解决方案:

<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild">
  <ItemGroup>
    <Content Include="images\**" />
  </ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)

正如克里斯在他的回答中提到的那样 - 即使您手动摆弄(添加/删除文件)目标目录,Visual Studio 也不会触及此<Target>部分.

请注意,您应该包含文件所在的子目录(在上面的例子中,它是images).Visual Studio/MSBuild会将这些文件放在项目结构中的同一目录中.如果不使用子目录,则文件将放置在项目结构的根目录中.

有关通配符的快速说明:

  • **表示一切递归(文件,子目录和其中的文件)
  • *.ext将包含ext在顶级目录中具有扩展名的所有文件,但不包括子目录
    • 例如,*.ext可能是*.png,*.js等等.任何文件扩展名都可以
  • **\*.ext将包括ext来自顶级目录和所有子目录的所有扩展文件.
  • 请参阅如何使用Nant/Ant命名模式的答案有关示例的更完整的解释.

完成后,请注意使用<Target>和不使用它之间存在差异.

使用此<Target>方法,Visual Studio 将不会在解决方案资源管理器中显示文件.

<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild">
  <ItemGroup>
    <Content Include="images\**" />
  </ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)

<Target>方法指示Visual Studio 在解决方案资源管理器中显示文件.这个的缺点是对自动目录的任何操作都将导致Visual Studio覆盖通配符条目.还应注意,下面的方法只会在VS中打开解决方案/项目时更新解决方案资源管理器.即使解决方案资源管理器的"刷新"工具栏按钮也不会这样做.

<ItemGroup>
  <Content Include="images\**" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

  • 感谢您进行实验并指出使用 &lt;Target&gt; 和不使用 &lt;Target&gt; 之间的差异。对通配符的详细信息也有很好的解释。 (2认同)

Ste*_*ens 10

您可以使用框架的System.IO.Directory.GetFile(string)方法及其重载来递归地包含所有文件.

  <ItemGroup>
    <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" />
    <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" />
  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

  • 我对此进行了更多实验,结果证明这与"Include ="**\*.ext"`和通配符具有相同的局限性. (2认同)