Apakah ada cara untuk memasukkan file konten ke dalam file proyek asp.net secara otomatis?

88

Saya sering menambahkan banyak file konten (kebanyakan gambar dan js) ke proyek ASP.NET saya. Saya menggunakan sistem VS publish, dan saat mempublikasikan, file baru tidak dipublikasikan sampai saya memasukkannya ke dalam proyek. Saya ingin memasukkan semua file secara otomatis dalam direktori tertentu. Apakah ada cara untuk menentukan direktori mana yang harus otomatis disertakan dalam file csproj atau di mana pun?

Marko
sumber
lihat: ini dapat membantu Anda stackoverflow.com/questions/1743432/…
Saar
1
tidak persis seperti yang saya cari
Marko
Saya memperbarui jawaban saya tentang masalah Anda saat memodifikasi folder di dalam browser solusi vs Anda.
Filburt

Jawaban:

135

Untaian lama, saya tahu, tetapi saya menemukan cara untuk melakukan ini yang terus saya lupakan, dan dalam pencarian saya untuk menemukannya untuk terakhir kalinya, saya tersandung pada pertanyaan ini. Cara terbaik yang saya temukan untuk ini adalah dengan menggunakan target BeforeBuild di file .csproj.

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

VS 2010 tidak akan menyentuh bagian ini, dan memastikan bahwa file Anda disertakan sebagai konten setiap kali proyek dibuat.

Chris
sumber
Apa arti dari .less? Dan apa artinya seluruh string **\*.less?
Pengguna Terdaftar
3
File .less adalah file css yang dimaksudkan untuk diurai oleh preprocessor Less CSS. Google "kurangi titik" untuk info lebih lanjut tentang itu. Ekspresi **\*.lessberarti menyertakan semua file * .less di semua direktori. Dalam bahasa MSBUILD, ** berarti 'semua direktori secara rekursif'
Chris
4
Setidaknya di VS 2012, segera setelah Anda menambah / menghapus file dari proyek dan menyimpannya, sayangnya ini akan diperluas ke daftar lengkap. :(
Chris Phillips
3
Ini berfungsi untuk situasi saya hanya setelah mengubah BeforeBuild menjadi AfterBuild, build saya memulai skrip PowerShell yang memindahkan file, yang kemudian tidak akan diambil oleh upaya penerapan web biru karena mereka hanya ada setelah build berhasil. Melihat "BeforeBuild" membuatku penasaran bahwa mungkin ada "AterBuild" juga. Semoga ini bisa membantu orang lain.
Luke Rice
1
@ John lihat jawaban saya di bawah ini untuk memperbaiki VS2015 +.
Jesse
55

Anda cukup memperluas file .csproj situs web Anda. Cukup tambahkan folder root konten Anda dengan wildcard rekursif:

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

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

Melakukannya membuat folder ini dan semua konten di bawah terlihat di dalam browser solusi Anda.

Jika Anda mencoba menyembunyikan folder di dalam browser solusi dengan menentukan

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

itu tidak akan dipublikasikan.


Memperbarui

Karena Anda sudah menemukan wildcard akan diganti segera setelah Anda menyentuh folder di dalam solusi Anda karena proyek VS tidak dirancang untuk berisi konten yang berubah-ubah.

Jadi, Anda harus memastikan folder dan isinya tidak pernah diubah dari dalam VS - menambah atau menghapus file hanya dapat dilakukan pada sistem file ... yang Anda inginkan karena saya memahami pertanyaan Anda.

Akan lebih mudah jika folder dapat disembunyikan di VS tetapi saya tidak dapat menemukan cara untuk menyembunyikannya DAN mempublikasikannya.

Pendekatan lain yang tidak berhasil adalah memasukkan folder dengan CreateItemTugas. Hal ini mengakibatkan konten folder dipublikasikan ke \ bin \ app.publish \ ... dan tidak dapat diyakinkan untuk menerbitkannya bersama dengan item konten di dalam .csproj jadi saya tidak menyajikannya dalam jawaban saya.

Filburt
sumber
3
Ini berfungsi sampai saya menambah atau menghapus file secara manual. Setelah baris itu <Content Include = "Images * *. " /> Menghilang dari file proyek.
Marko
2
@Marko benar. Setelah menambahkannya <Content Include="Images\**\*.*" />berhasil. Setelah Anda menambahkan lebih banyak gambar, .csproj diubah dan kembali ke daftar semua file dalam gambar / ... dan <Content Include = "Images * *. " /> Hilang.
Ravi Ram
Tempelkan kode ini dalam file .proj terpisah dan panggil dari target build sebelumnya dalam file .csproj.
NL - Minta maaf kepada Monica
21

Bagi mereka yang mengalami masalah dalam menggunakan jawaban Chris , ini adalah solusi untuk Visual Studio 2012 dan yang lebih baru:

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

Seperti yang dikatakan Chris dalam jawabannya - Visual Studio tidak akan menyentuh <Target>bagian ini , meskipun Anda secara manual mengutak-atik (menambahkan / menghapus file) dengan direktori target.

Harap dicatat bahwa Anda harus menyertakan subdirektori tempat file-file tersebut berada (dalam kasus di atas, itu images). Visual Studio / MSBuild akan menempatkan file tersebut di direktori yang sama dalam struktur proyek. Jika Anda tidak menggunakan subdirektori, file akan ditempatkan di root struktur proyek.

Untuk penjelasan singkat tentang wildcard:

  • **Berarti semuanya secara rekursif (file, subdirektori, dan file di dalamnya)
  • *.extakan menyertakan semua file dengan ekstensi extdi dalam direktori level teratas, tetapi tidak subdirektori
    • Misalnya, *.extbisa *.png, *.js, dll Setiap ekstensi file akan bekerja
  • **\*.extakan menyertakan semua file dengan ekstensi extdari direktori level teratas dan semua subdirektori.
  • Lihat jawaban dari Bagaimana cara menggunakan pola penamaan Nant / Ant? untuk penjelasan yang lebih lengkap beserta contohnya.

Untuk penyelesaiannya, perlu diketahui bahwa ada perbedaan antara menggunakan <Target>dan tidak menggunakannya.

Dengan <Target>pendekatan ini, Visual Studio tidak akan menampilkan file di dalam Solution Explorer.

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

<Target>Pendekatan non- akan memerintahkan Visual Studio untuk menampilkan file dalam Solution Explorer. Kekurangannya adalah manipulasi direktori otomatis akan menyebabkan Visual Studio menimpa entri wildcard. Perlu juga dicatat bahwa pendekatan di bawah ini hanya akan memperbarui Penjelajah Solusi setelah membuka Solusi / Proyek di VS. Bahkan tombol toolbar "refresh" Solution Explorer tidak akan melakukannya.

<ItemGroup>
  <Content Include="images\**" />
</ItemGroup>
Jesse
sumber
1
Terima kasih telah bereksperimen dan menunjukkan perbedaan antara menggunakan <Target> dan tidak. Penjelasan bagus tentang detail wildcard juga.
Kurt Hutchinson
@Kurtinson - tidak masalah. =)
Jesse
Saya yakin solusi ini perlu dipoles. Ketika Anda menginstruksikan target untuk dijalankan setelah "BeforeBuild" maka secara teori ini juga bisa terjadi SETELAH publikasi. Solusi saat ini mungkin berhasil karena keberuntungan.
Imre Pühvel
@ ImrePühvel bagaimana Anda mengetahui mempublikasikan terjadi sebelum itu BeforeBuildacara? MSBuild harus terlebih dahulu membangun proyek dan binari sebelum dapat mempertimbangkan untuk menerbitkan.
Jesse
1
Saya tidak mengklaim mempublikasikan terjadi sebelum pembuatan, tetapi deklarasi tersebut tidak menjamin bahwa item ditambahkan ke konten sebelum dipublikasikan. Dari contoh kode: .. AfterTargets="BeforeBuild". Artinya, target khusus Anda harus dijalankan setelah BeforeBuild, tetapi tidak menentukan berapa banyak setelahnya. Padahal, kesalahan saya, dengan algoritme pengurutan target saat ini seharusnya ok: msdn.microsoft.com/en-us/library/ee216359.aspx
Imre Pühvel
10

Anda dapat menggunakan metode framework System.IO.Directory.GetFile(string)dan kelebihannya untuk menyertakan semua file secara rekursif.

  <ItemGroup>
    <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Scripts\', '*.js', SearchOption.AllDirectories))" />
    <Content Include="$([System.IO.Directory]::GetFiles('$(ProjectDir)Images\', '*.png', SearchOption.AllDirectories))" />
  </ItemGroup>
Steven Liekens
sumber
Ini sangat membantu saya; Saya memiliki banyak direktori dengan kedalaman beberapa level dan banyak file yang ingin saya sertakan secara otomatis dan ini mengubah semua konten itu menjadi satu. Terima kasih!
Jay Otterbein
2
Saya bereksperimen dengan ini lagi dan ternyata ini memiliki semua batasan yang sama seperti Include="**\*.ext"dengan wildcard.
Steven Liekens
Wow, apakah file proyek menyertakan run PowerShell? Apakah itu kotak pasir sama sekali? Itu adalah eksploitasi yang menunggu untuk terjadi.
Brain2000
Ini bukan PowerShell. MSBuild memiliki sintaksnya sendiri untuk menjalankan metode statis. Menurut dokumen, ini terbatas pada kelas sistem. docs.microsoft.com/en-us/visualstudio/msbuild/… Meskipun saya yakin Anda bisa <Exec> Powerhell dengan argumen apa pun ...
Steven Liekens
3

Saya telah menulis bagaimana saya bisa mendapatkan konten yang dibuat dengan skrip PowerShell kecil:

$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`" /> "
}

Ini harus menghasilkan pernyataan include yang diperlukan pada prompt PowerShell

thom schumacher
sumber
2

Anda dapat menambahkan file dengan link seperti ini, file tersebut dapat dicari, dapat dilihat, tetapi file tersebut tidak melakukan pembayaran jika Anda mencoba mengubahnya, juga studio visual membiarkan wildcard di tempatnya:

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

Ini masuk ke dalam file .proj.

chongo2002
sumber
1
Saya mencoba ini dan VS mengganti wildcard dengan file individual ketika saya menambah atau menghapus file menggunakan VS.
carlin.scott
Ini sangat elegan, tetapi Anda harus menghapus karakter pengganti dari target tautan
SimSimY
1

Tidak setahu saya; namun saran saya adalah menempelkannya ke dalam proyek karena ini akan menyertakannya secara default. Jadi, alih-alih menempelkannya ke direktori melalui Explorer, gunakan Visual Studio untuk menempelkan file ke dalam folder.

kamranicus
sumber
-1

Saya menyadari bahwa solusi terbaik untuk ini adalah menambahkan file secara manual, satu per satu. Jika Anda memiliki ratusan seperti yang saya lakukan, itu hanya masalah beberapa jam. Lucunya di tahun 2016 dengan VS 2015 masalah serius ini masih belum terpecahkan. Ahh, betapa aku mencintai Xcode.

Marcin Skoczylas
sumber