Есть ли способ автоматически включать файлы содержимого в файл проекта asp.net?

86

Я часто добавляю много файлов содержимого (в основном изображений и js) в свой проект ASP.NET. Я использую систему публикации VS, и при публикации новые файлы не публикуются, пока я не включу их в проект. Я хотел бы автоматически включать все файлы в указанный каталог. Есть ли способ указать, какие каталоги должны быть автоматически включены в файл csproj или где-либо еще?

Марко
источник
см .: это может помочь вам stackoverflow.com/questions/1743432/…
Саар,
1
не совсем то, что я ищу
Марко
Я обновил свой ответ, касающийся вашей проблемы, при изменении папки в браузере решения vs.
Filburt

Ответы:

134

Старая ветка, я знаю, но я нашел способ сделать это, о чем постоянно забываю, и, пытаясь найти его в последний раз, я наткнулся на этот вопрос. Лучший способ, который я нашел для этого, - использовать цель BeforeBuild в файле .csproj.

<Target Name="BeforeBuild">
    <ItemGroup>
        <Content Include="**\*.less" />
    </ItemGroup>
</Target>

VS 2010 не будет касаться этого раздела и гарантирует, что ваши файлы будут добавляться в качестве содержимого при каждой сборке проекта.

Крис
источник
В чем смысл .less? А что значит вся строка **\*.less?
Зарегистрированный пользователь
3
Файлы .less - это файлы css, предназначенные для анализа препроцессором Less CSS. Google "точка меньше" для получения дополнительной информации об этом. Выражение **\*.lessозначает включать все файлы * .less во все каталоги. На языке MSBUILD ** означает «все каталоги рекурсивно»
Крис,
4
По крайней мере, в VS 2012, как только вы добавляете / удаляете файл из проекта и сохраняете, он, к сожалению, расширяется до полного списка. :(
Крис Филлипс
3
Это сработало в моей ситуации только после изменения BeforeBuild на AfterBuild, моя сборка запускает сценарий PowerShell, который перемещает файлы, которые затем не будут приняты моей попыткой веб-развертывания Azure, потому что они существовали только после успешной сборки. Увидев «BeforeBuild», я понял, что, вероятно, существует и «AterBuild». Надеюсь, это поможет кому-то другому.
Люк Райс,
1
@John см. Мой ответ ниже, чтобы исправить VS2015 +.
Джесси
54

Вы просто можете расширить файл .csproj на своем веб-сайте. Просто добавьте корневую папку содержимого с рекурсивным подстановочным знаком:

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

    <!-- your static content you like to publish -->
    <Content Include="Images\**\*.*" />
</ItemGroup>
...

Это сделает эту папку и все содержимое ниже видимым в браузере решения.

Если вы попытаетесь скрыть папку внутри браузера решения, указав

<Content Include="Images\**.*.*">
    <Visible>false</Visible>
</Content>

он не будет опубликован.


Обновить

Как вы уже обнаружили, подстановочный знак будет заменен, как только вы коснетесь папки внутри вашего решения, потому что проекты VS не предназначены для содержания произвольного контента.

Поэтому вам нужно будет убедиться, что папка и ее содержимое никогда не изменяются изнутри VS - добавление или удаление файлов может выполняться только в файловой системе ... это то, что вы хотели, поскольку я понял ваш вопрос.

Было бы проще, если бы папку можно было скрыть в VS, но я не мог найти способ скрыть ее И опубликовать.

Еще один неудачный подход - включить папку CreateItemЗадачей. Это привело к тому, что содержимое папки было опубликовано в \ bin \ app.publish \ ... и не удалось убедить опубликовать его вместе с элементами содержимого внутри .csproj, поэтому я не представил его в своем ответе.

Филбурт
источник
3
Он работает, пока я не добавлю или не удалю файл вручную. После этого строка <Content Include = "Images * *. " /> Исчезает из файла проекта.
Марко
2
@Marko прав. После добавления <Content Include="Images\**\*.*" />заработало. После добавления дополнительных изображений .csproj изменяется и возвращается к списку всех файлов в images / ..., а <Content Include = "Images * *. " /> Исчезает.
Рави Рам,
Поместите этот код в отдельный файл .proj и вызовите его из целевого объекта до сборки в файле .csproj.
NL - Извинитесь перед Моникой
21

Для тех, у кого есть проблемы с использованием ответа Криса , это решение для Visual Studio 2012 и новее:

<Target Name="ContentsBeforeBuild" AfterTargets="BeforeBuild">
  <ItemGroup>
    <Content Include="images\**" />
  </ItemGroup>
</Target>

Как упомянул Крис в своем ответе, 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>

Непостоянство <Target>подход будет инструктировать Visual Studio , чтобы показать файлы в обозревателе решений. Недостатком этого является то, что любые манипуляции с автоматическими каталогами заставят Visual Studio переопределить запись с подстановочными знаками. Следует также отметить , что подход ниже будет только обновить в Solution Explorer при открытии Solution / Проект в VS. Даже кнопка панели инструментов «Обновить» в обозревателе решений не сделает этого.

<ItemGroup>
  <Content Include="images\**" />
</ItemGroup>
Джесси
источник
1
Спасибо за эксперименты и за указание различий между использованием <Target> и нет. Отличное объяснение деталей подстановочных знаков тоже.
Курт Хатчинсон
@KurtHutchinson - без проблем. =)
Джесси
Я считаю, что это решение требует доработки. Когда вы указываете цели запускаться после «BeforeBuild», то теоретически это также может произойти ПОСЛЕ публикации. Текущее решение, вероятно, работает благодаря удаче.
Imre Pühvel
@ ImrePühvel как вы вычисляете публиковать происходит до того в BeforeBuildслучае? MSBuild должен сначала построить проект и двоичные файлы, прежде чем даже рассматривать возможность публикации.
Джесси
1
Я не утверждал, что публикация должна происходить до сборки, но это объявление не гарантирует, что элементы будут добавлены в контент перед публикацией. Из образца кода: .. AfterTargets="BeforeBuild". Это означает, что ваша настраиваемая цель должна выполняться после BeforeBuild, но не указывает, сколько после нее. Хотя, моя ошибка, по текущему алгоритму целевого упорядочивания все должно быть в порядке: msdn.microsoft.com/en-us/library/ee216359.aspx
Имре Пювел
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>
Стивен Ликенс
источник
Это было для меня большим подспорьем; У меня есть несколько каталогов на несколько уровней глубины и много файлов, которые я хотел включить автоматически, и это превратило все это содержимое в один. Благодарность!
Джей Оттербейн
2
Я еще поэкспериментировал с этим, и оказалось, что это имеет те же ограничения, что и Include="**\*.ext"с подстановочными знаками.
Стивен Ликенс
Вау, а файл проекта включает в себя запуск PowerShell? Это вообще песочница? Это эксплойт, который ждет своего часа.
Brain2000
Это не PowerShell. MSBuild имеет собственный синтаксис для вызова статических методов. Согласно документам, это ограничено системными классами. docs.microsoft.com/en-us/visualstudio/msbuild/… Хотя я уверен, что вы можете просто использовать <Exec> powershell с любыми аргументами ...
Стивен Ликенс,
3

Я написал, как мне удалось получить контент, созданный с помощью небольшого скрипта PowerShell:

$folders = Get-ChildItem .\ -r -Directory
$filtered = $folders |Select-Object @{Name='FullName';Expression={$_.fullname.replace($pwd,'')}}, @{Name='FolderDepth';Expression={($_.fullname.Split('\').Count) - ($Pwd.Path.split('\').count)}} | Sort-Object -Descending FullName,folderDepth 
$basefolders = $filtered | Where-Object{$_.folderdepth -eq 1}
$basefoldersobj = @()
foreach($basefolder in $basefolders)
{
  $basefoldername =$baseFolder.fullname
  $filteredbase = $filtered -match "\$basefoldername\\" | Sort-Object -Descending FolderDepth | Select-Object -first 1
  if($filteredbase -eq $null)
  {
    $filteredbase = $filtered -match "\$basefoldername" | Sort-Object -Descending FolderDepth | Select-Object -first 1
  }
  $obj = New-Object psobject
  Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Folder' -Value $basefolder.fullname.trim('\')
  Add-member -InputObject $obj -MemberType NoteProperty -Name 'DeepestPath' -Value $filteredbase.folderDepth
  $basefoldersobj += $obj
}
$include = '*.*'
foreach($bfolderObj in $basefoldersobj)
{
  $includecount = ''
  $includecount = "\$include" * ($bfolderObj.Deepestpath)
  Write-Output "<content Include=`"$($bfolderObj.folder)$includecount`" /> "
}

Это должно создать необходимый оператор include в командной строке PowerShell.

Том Шумахер
источник
2

Вы можете добавлять файлы с такими ссылками, они доступны для поиска и просмотра, но они не извлекаются, если вы пытаетесь их изменить, также Visual Studio оставляет подстановочные знаки на месте:

  <ItemGroup>
    <Content Include="..\Database Schema\Views\*.sql">
      <Link>Views\*.sql</Link>
    </Content>
  </ItemGroup>

Это находится внутри файла .proj.

chongo2002
источник
1
Я пробовал это, и VS заменяет подстановочный знак отдельными файлами, когда я добавляю или удаляю файл с помощью VS.
carlin.scott
Это очень элегантно, но вам следует удалить подстановочный знак из цели ссылки
SimSimY
1

Насколько мне известно, нет; однако я предлагаю вставить их в проект, так как они будут включены по умолчанию. Поэтому вместо того, чтобы вставлять их в каталог через проводник, используйте Visual Studio для вставки файлов в папки.

Камраникус
источник
-1

Я понял, что лучшее решение для этого - вручную добавлять файлы по одному. Если у вас их сотни, как у меня, это всего лишь вопрос нескольких часов. Забавно, что даже в 2016 году с VS 2015 эта серьезная проблема все еще не решена. Ах, как я люблю Xcode.

Марцин Скочилас
источник