2

I am building a Visual Studio 2015 Web API 2 template for my company. It is a multiproject template. I have it all setup and it is working fine except for the Nuget packages. They will not install.

I followed the steps outlined here: https://learn.microsoft.com/en-us/nuget/visual-studio-extensibility/visual-studio-templates.

Here is what I have setup:

  • The .nupkg files in my vsix project. If I unzip the vsix, I see them in the Packages folder. (I copied these .nupkg files from the packages folder in my original solution I made.)

  • I have listed every Nuget package as an asset in my source.extension.vsixmanifest file (found in the vsix project).

Here is an example:

<Asset Type="AutoMapper.5.2.0.nupkg" d:Source="File" Path="Packages\AutoMapper.5.2.0.nupkg" d:VsixSubPath="Packages" />
  • In my sub-project .vstemplate files I have added the nuget wizard and listed the packages needed for that template.

Here is an example of one of my subprojects (the first wizard is my vsix project):

<WizardExtension>
    <Assembly>MyVsixProject, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=52156a0ac017d515</Assembly>
    <FullClassName>MyVsixProject.WizardImplementation</FullClassName>
</WizardExtension>
<WizardExtension>
    <Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
    <FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
<WizardData>
    <packages repository="extension" repositoryId="MyVsixProject.8b0b584a-d7ab-4608-e317-84e1aa773a01">
        <package id="AutoMapper" version="5.2.0" />            
        <package id="EntityFramework" version="6.1.3" />
        <package id="Microsoft.Net.Compilers" version="1.3.2" />
        <package id="SimpleInjector" version="3.2.0" />            
    </packages>
</WizardData>

Near as I can tell, I am following the instructions.

However, when I run the template, the solution level folder does not have a packages folder and all my nuget based references are broken.

Vaccano
  • 78,325
  • 149
  • 468
  • 850

2 Answers2

2

Turns out that you have to have all the Nuget artifacts gone from your template. (As if it has not ever been installed.) Then the Nuget wizard will install correctly.

The link I mentioned above lists this as a "Best Practice" not a "It will not work if you don't do it", like it really is.

This is my script that I run in my build engine to remove the nuget stuff from my working project:

# DO NOT CALL THIS DIRECTLY!  IT SHOULD ONLY BE CALLED BY THE BUILD SYSTEM.
# IF YOU CALL THIS DIRECTLY then the projects will have all of their nuget references removed.
#
# For the template to be able to install the nuget stuff, it needs it to be in a state as if
# it has never been installed.  This script removes:
#     • The packages.config files
#     • Removes <None Include="packages.config" /> from any csproj files
#     • Compiler references that are added by nuget
#     • Removes any references from csproj files that have a hint path that contains '..\packages\

# Find all packages.config files and delete them
get-childitem ./ -include packages.config -recurse | foreach ($_) {remove-item $_.fullname -force}

# Find all .csproj files 
$csProjFiles = get-childitem ./ -include *.csproj -recurse 

# Remove the packages.config include from the csproj files.
$csProjFiles | foreach ($_) {$currentFile = $_; (get-content $_) | Where-Object {$_ -notmatch 'Include="packages.config"'} | Set-Content $currentFile -force}

# Remove any compiler references added by the compiler nuget packages.
$csProjFiles | foreach ($_) {$currentFile = $_; (get-content $_) | Where-Object {$_ -notmatch 'build\\Microsoft.Net.Compilers.props'} | Set-Content $currentFile -force}
$csProjFiles | foreach ($_) {$currentFile = $_; (get-content $_) | Where-Object {$_ -notmatch 'build\\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'} | Set-Content $currentFile -force}

# Remove any references that have a hint path that contains '..\packages\'
foreach ($csProjFile in $csProjFiles){
    [xml] $csProjFileXml = get-content $csProjFile;
    foreach ($itemGroup in $csProjFileXml.Project.ItemGroup) {  
        foreach ($reference in $itemGroup.Reference) {
            foreach ($hintPath in $reference.HintPath){
                if ($hintPath -like '*..\packages\*'){
                    $itemGroup.RemoveChild($reference)
                }           
            }           
        }
    }
    $csProjFileXml.Save($csProjFile)
}
Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • This is the only thing that helped me after hours of trial-and-error. – themightylc Feb 27 '18 at 16:22
  • Hi, I am trying this solution but when I remove the packages.config file (i just have 1), then when I create a project from my template, it doesn't restore any of the nuget packages. How will the project know which nuget packges to restore without the packages.config file? – Quintonn Jan 28 '19 at 11:12
1

The Assets section of in file source.extension.vsixmanifest should be:

<Asset d:Source="File" Type="AutoMapper.5.2.0.nupkg" Path="Packages\AutoMapper.5.2.0.nupkg" d:VsixSubPath="Packages" />

That instructions which you followed is seemingly out of date. You can refer to the similar issue for detail.

Community
  • 1
  • 1
Leo Liu
  • 71,098
  • 10
  • 114
  • 135
  • That looks the same as what I posted except the order of the "source" attribute. Is the order really important – Vaccano Feb 24 '17 at 15:05
  • You can have try follow steps in this post http://stackoverflow.com/questions/18857996/multi-project-solution-templates-for-visual-studio-2012-with-vsix-installer-an to create multiproject templates with VSIX installer and Nuget packages. Hope that help you. – Leo Liu Feb 26 '17 at 05:44