C'è un modo per includere automaticamente i file di contenuto nel file di progetto asp.net?


88

Aggiungo spesso molti file di contenuto (principalmente immagini e js) al mio progetto ASP.NET. Uso il sistema di pubblicazione VS e durante la pubblicazione i nuovi file non vengono pubblicati finché non li includo nel progetto. Vorrei includere automaticamente tutti i file nella directory specificata. C'è un modo per specificare quali directory dovrebbero essere incluse automaticamente nel file csproj o in qualsiasi altro luogo?


vedi: questo può aiutarti a stackoverflow.com/questions/1743432/…
Saar

1
non esattamente quello che sto cercando
Marko

Ho aggiornato la mia risposta in merito al tuo problema durante la modifica della cartella all'interno del tuo browser vs solution.
Filburt

Risposte:


135

Vecchio filo, lo so, ma ho trovato un modo per farlo che continuo a dimenticare, e nella mia ricerca per trovarlo un'ultima volta, mi sono imbattuto in questa domanda. Il modo migliore che ho trovato è utilizzare l'obiettivo BeforeBuild nel file .csproj.

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

VS 2010 non toccherà questa sezione e garantisce che i file siano inclusi come contenuto ogni volta che il progetto viene creato.


Qual è il significato di .less? E cosa significa l'intera stringa **\*.less?
Utente registrato il

3
I file .less sono file CSS pensati per essere analizzati dal preprocessore Less CSS. Google "punto meno" per maggiori informazioni su questo. L'espressione **\*.lesssignifica includere tutti i file * .less in tutte le directory. In MSBUILD parlare, ** significa "tutte le directory in modo ricorsivo"
Chris

4
Almeno in VS 2012, non appena aggiungi / rimuovi un file dal progetto e lo salvi, questo purtroppo viene espanso all'elenco completo. :(
Chris Phillips

3
Questo ha funzionato per la mia situazione solo dopo aver cambiato BeforeBuild in AfterBuild, la mia build dà il via a uno script PowerShell che sposta i file in giro, che quindi non sarebbero stati rilevati dal mio tentativo di distribuzione Web azzurro perché esistevano solo dopo che la build era riuscita. Vedere "BeforeBuild" mi ha fatto capire che probabilmente c'era anche un "AterBuild". Spero che questo aiuti qualcun altro.
Luke Rice

1
@ John vedi la mia risposta di seguito per una correzione a VS2015 +.
Jesse

55

Puoi semplicemente estendere il file .csproj del tuo sito web. Basta aggiungere la cartella principale del contenuto con un carattere jolly ricorsivo:

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

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

In questo modo, questa cartella e tutto il contenuto sottostante saranno visibili nel browser della soluzione.

Se provi a nascondere la cartella all'interno del browser della soluzione specificando

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

non sarà pubblicato.


Aggiornare

Come hai già scoperto, il carattere jolly verrà sostituito non appena tocchi la cartella all'interno della tua soluzione perché i progetti VS non sono progettati per contenere contenuti arbitrari.

Quindi dovrai assicurarti che la cartella e il suo contenuto non vengano mai modificati dall'interno di VS - l'aggiunta o la rimozione di file può essere eseguita solo sul file system ... che è quello che volevi come ho capito la tua domanda.

Sarebbe più facile se la cartella potesse essere nascosta in VS ma non riuscivo a trovare un modo per nasconderla E pubblicarla.

Un altro approccio non riuscito è stato quello di includere la cartella in un'attività CreateItem. Ciò ha comportato la pubblicazione del contenuto della cartella su \ bin \ app.publish \ ... e non potevo essere convinto a pubblicarlo insieme agli elementi di contenuto all'interno di .csproj, quindi non l'ho presentato nella mia risposta.


3
Funziona finché non aggiungo o rimuovo il file manualmente. Dopo quella riga <Content Include = "Images * *. " /> Scompare dal file di progetto.
Marko

2
@Marko è corretto. Dopo <Content Include="Images\**\*.*" />averlo aggiunto ha funzionato. Una volta aggiunte altre immagini, il file .csproj viene modificato e torna a elencare tutti i file nelle immagini / ... e <Content Include = "Images * *. " /> È scomparso.
Ravi Ram

Incolla questo codice in un file .proj separato e chiamalo dalla destinazione della build precedente nel file .csproj.
NL - Chiedi scusa a Monica il

21

Per coloro che hanno problemi con la risposta di Chris , questa è la soluzione per Visual Studio 2012 e versioni successive:

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

Come ha menzionato Chris nella sua risposta, Visual Studio non toccherà questa <Target>sezione, anche se giocherelli manualmente (aggiungendo / rimuovendo file) con la directory di destinazione.

Nota che dovresti includere una sottodirectory in cui si trovano i file (nel caso sopra, è images). Visual Studio / MSBuild inserirà questi file nella stessa directory all'interno della struttura del progetto. Se non utilizzi una sottodirectory, i file verranno posizionati alla radice della struttura del progetto.

Per una rapida spiegazione dei caratteri jolly:

  • **significa tutto in modo ricorsivo (file, sottodirectory e file al loro interno)
  • *.extincluderà tutti i file con estensione extall'interno della directory di primo livello, ma non le sottodirectory
    • Ad esempio, *.extpotrebbe essere *.png, *.jsecc Qualsiasi estensione del file funzionerà
  • **\*.extincluderà tutti i file con estensione extdalla directory di primo livello e tutte le sottodirectory.
  • Vedere la risposta in Come si utilizzano i modelli di denominazione Nant / Ant? per una spiegazione più completa con esempi.

Per il completamento, tieni presente che c'è una differenza tra l'utilizzo <Target>e il non utilizzo.

Con l' <Target>approccio, Visual Studio non mostrerà i file all'interno di Esplora soluzioni.

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

Il mancato <Target>approccio indicherà a Visual Studio di mostrare i file all'interno di Esplora soluzioni. Lo svantaggio di questo è che qualsiasi manipolazione delle directory automatiche farà sì che Visual Studio sovrascriva la voce jolly. Va inoltre notato che l'approccio seguente aggiornerà Esplora soluzioni solo all'apertura della soluzione / progetto in VS. Anche il pulsante "Aggiorna" della barra degli strumenti di Esplora soluzioni non lo farà.

<ItemGroup>
  <Content Include="images\**" />
</ItemGroup>

1
Grazie per aver sperimentato e sottolineato le differenze tra l'utilizzo di <Target> e non. Ottima anche la spiegazione dei dettagli dei caratteri jolly.
Kurt Hutchinson

@KurtHutchinson - nessun problema. =)
Jesse

Credo che questa soluzione debba essere lucidata. Quando si istruisce il target a eseguire "BeforeBuild", in teoria ciò potrebbe accadere anche DOPO la pubblicazione. La soluzione attuale probabilmente funziona per fortuna.
Imre Pühvel

@ ImrePühvel come si fa a capire pubblicare accade prima che l' BeforeBuildevento? MSBuild deve prima compilare il progetto e i file binari prima di poter prendere in considerazione la pubblicazione.
Jesse

1
Non ho affermato che la pubblicazione avvenga prima della compilazione, ma che la dichiarazione non garantisce che gli elementi vengano aggiunti al contenuto prima della pubblicazione. Dal codice di esempio: .. AfterTargets="BeforeBuild". Significa che il tuo target personalizzato deve essere eseguito dopo BeforeBuild, ma non specifica quanto tempo dopo. Tuttavia, errore mio, con l'attuale algoritmo di ordinamento del target dovrebbe essere ok: msdn.microsoft.com/en-us/library/ee216359.aspx
Imre Pühvel

10

È possibile utilizzare il System.IO.Directory.GetFile(string)metodo del framework e i relativi overload per includere in modo ricorsivo tutti i file.

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

Questo è stato di grande aiuto per me; Ho più directory profonde alcuni livelli e molti file che volevo includere automaticamente e questo ha trasformato tutti quei contenuti in uno solo. Grazie!
Jay Otterbein

2
Ho sperimentato ancora un po 'e ho scoperto che ha le stesse limitazioni dei Include="**\*.ext"caratteri jolly.
Steven Liekens

Wow, il file di progetto include l'esecuzione di PowerShell? È davvero sandbox? È un exploit in attesa di accadere.
Brain2000

Non è PowerShell. MSBuild ha una propria sintassi per invocare metodi statici. Secondo i documenti, questo è limitato a classi di sistema. docs.microsoft.com/en-us/visualstudio/msbuild/… Anche se sono sicuro che puoi semplicemente <Exec> powershell con qualsiasi argomento ...
Steven Liekens

3

Ho scritto come sono riuscito a ottenere i contenuti inclusi creati con un piccolo script 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`" /> "
}

Questo dovrebbe produrre la necessaria istruzione include al prompt di PowerShell


2

Puoi aggiungere file con collegamenti come questo, sono ricercabili, visualizzabili, ma non effettuano il checkout se provi a modificarli, inoltre Visual Studio lascia i caratteri jolly al loro posto:

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

Questo va all'interno del file .proj.


1
Ho provato questo e VS sostituisce il carattere jolly con i singoli file quando aggiungo o rimuovo un file utilizzando VS.
carlin.scott

Questo è molto elegante, ma dovresti rimuovere il carattere jolly dalla destinazione del collegamento
SimSimY

1

Non a mia conoscenza; tuttavia il mio suggerimento è di incollarli nel progetto poiché questo li includerà per impostazione predefinita. Quindi, invece di incollarli nella directory tramite Explorer, usa Visual Studio per incollare i file nelle cartelle.


-1

Mi sono reso conto che la soluzione migliore per questo è aggiungere manualmente i file, uno per uno. Se ne hai centinaia come me, era solo questione di poche ore. Divertente che anche nel 2016 con VS 2015 questo grave problema non sia stato ancora risolto. Ahh, quanto amo Xcode.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.