web-dev-qa-db-fra.com

Existe-t-il un moyen d'inclure automatiquement des fichiers de contenu dans le fichier de projet asp.net?

J'ajoute fréquemment de nombreux fichiers de contenu (principalement des images et des js) à mon projet ASP.NET. J'utilise le système de publication VS et lors de la publication, les nouveaux fichiers ne sont pas publiés tant que je ne les ai pas inclus dans le projet. Je voudrais inclure automatiquement tous les fichiers dans le répertoire spécifié. Existe-t-il un moyen de spécifier les répertoires à inclure automatiquement dans le fichier csproj ou ailleurs?

78
Marko

Vieux fil, je sais, mais j'ai trouvé un moyen de le faire que j'oublie toujours, et en cherchant à le trouver une dernière fois, je suis tombé sur cette question. Le meilleur moyen que j'ai trouvé pour cela est d'utiliser la cible BeforeBuild dans le fichier .csproj.

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

VS 2010 ne touchera pas à cette section et garantit que vos fichiers sont inclus en tant que contenu chaque fois que le projet est construit.

128
Chris

Vous pouvez simplement étendre le fichier .csproj de votre site Web. Ajoutez simplement votre dossier racine de contenu avec un caractère générique récursif:

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

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

Cela rend ce dossier et tout le contenu ci-dessous visibles dans le navigateur de votre solution.

Si vous essayez de masquer le dossier dans le navigateur de solutions en spécifiant

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

il ne sera pas publié.


Mise à jour

Comme vous l'avez déjà découvert, le caractère générique sera remplacé dès que vous toucherez le dossier dans votre solution car les projets VS ne sont pas conçus pour contenir du contenu arbitraire.

Vous devrez donc vous assurer que le dossier et son contenu ne sont jamais modifiés depuis VS - l'ajout ou la suppression de fichiers ne peut se faire que sur le système de fichiers ... c'est ce que vous vouliez si j'ai bien compris votre question.

Ce serait plus facile si le dossier pouvait être caché dans VS mais je ne pouvais pas trouver un moyen de le cacher ET de le publier.

Une autre approche infructueuse a été d'inclure le dossier par une tâche CreateItem. Cela a entraîné la publication du contenu du dossier dans \bin\app.publish\... et n'a pas pu être convaincu de le publier avec le contenu articles à l'intérieur du .csproj donc je ne l'ai pas présenté dans ma réponse.

49
Filburt

Pour ceux qui ont des problèmes avec réponse de Chris , voici la solution pour Visual Studio 2012 et plus récent:

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

Comme Chris l'a mentionné dans sa réponse - Visual Studio ne le fera pas touchez ce <Target>, même si vous tripotez manuellement (ajout/suppression de fichiers) avec le répertoire cible.

Veuillez noter que vous devriez inclure un sous-répertoire où se trouvent les fichiers (dans le cas ci-dessus, c'est images). Visual Studio/MSBuild placera ces fichiers dans le même répertoire dans la structure du projet. Si vous n'utilisez pas de sous-répertoire, les fichiers seront placés à la racine de la structure du projet.

Pour une explication rapide des caractères génériques:

  • ** signifie tout récursivement (fichiers, sous-répertoires et fichiers dans ceux-ci)
  • *.ext inclura tous les fichiers avec l'extension ext dans le répertoire de niveau supérieur, mais pas les sous-répertoires
    • Par exemple, *.ext pourrait être *.png, *.js, etc. Any l'extension de fichier fonctionnera
  • **\*.ext inclura tous les fichiers avec l'extension ext du répertoire de niveau supérieur et tous les sous-répertoires.
  • Voir la réponse de Comment utiliser les modèles de nommage Nant/Ant? pour une explication plus complète avec des exemples.

Pour terminer, veuillez noter qu'il existe une différence entre l'utilisation de <Target> et ne pas l'utiliser.

Avec le <Target> approche, Visual Studio n'affichera pas les fichiers dans l'Explorateur de solutions.

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

Le non<Target> l'approche demandera à Visual Studio de afficher les fichiers dans la solution Explorateur. L'inconvénient de celui-ci est que toute manipulation des répertoires automatique obligera Visual Studio à remplacer l'entrée générique. Il convient également de noter que l'approche ci-dessous uniquement mettra à jour l'explorateur de solutions lors de l'ouverture de la solution/du projet dans VS. Même le bouton de la barre d'outils "Actualiser" de l'Explorateur de solutions ne le fera pas.

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

Vous pouvez utiliser la méthode System.IO.Directory.GetFile(string) du framework et ses surcharges pour inclure récursivement tous les fichiers.

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

J'ai écrit comment j'ai pu obtenir le contenu inclut créé avec un petit 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`" /> "
}

Cela devrait produire la déclaration d'inclusion nécessaire à l'invite PowerShell.

3
thom schumacher

Vous pouvez ajouter des fichiers avec des liens comme celui-ci, ils peuvent être recherchés, consultables, mais ils ne vérifient pas si vous essayez de les changer, également Visual Studio laisse les caractères génériques en place:

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

Cela va à l'intérieur du fichier .proj.

2
chongo2002

Pas à ma connaissance; cependant ma suggestion est de les coller dans le projet car cela les inclura par défaut. Ainsi, au lieu de les coller dans le répertoire via Explorer, utilisez Visual Studio pour coller les fichiers dans les dossiers.

1
kamranicus