NuGet restore

NuGet is a package manager like NPM for node.js or Gem for Ruby, and it is a dominant one in .NET.

You can handle dependency packages in two ways. You download them from NuGet server but also store them in your source control. Or, you just remember what packages you use in your project, and restore them on build. Node and Ruby guys always go for the 2nd option. .NET people used to do the first one, but now prefer the 2nd option. I agree to the 2nd option, restoring packages on build, rather than storing them in git repository. Git is for source code, NuGet repository is for packages.

The Visual Studio on my work machine isn’t set up for NuGet restore. “Restore” option is disabled, and when I download and build an open-source project, it can’t restore the packages and can’t build the solution.

I’ve checked if there’s work-around. It seems that the latest NuGet.exe can restore packages in command-line, regardless of your VS settings, which makes sense to me, as NuGet shouldn’t depend on the settings of your IDE. So update NuGet.exe to the latest.

exec { .\Tools\NuGet\NuGet.exe update -self }

Create an environmental variable, EnableNuGetPackageRestore, to true, but just for Process, not for Machine, not to impact other projects.

[Environment]::SetEnvironmentVariable("EnableNuGetPackageRestore", "true", "Process")

Then, you can safely restore your packages in command-line.

exec { .\Tools\NuGet\NuGet.exe restore ".\Src\$name.sln" | Out-Default } "Error restoring $name"

So, all the code in one place

Write-Host "Restoring"
[Environment]::SetEnvironmentVariable("EnableNuGetPackageRestore", "true", "Process")
exec { .\Tools\NuGet\NuGet.exe update -self }
exec { .\Tools\NuGet\NuGet.exe restore ".\Src\$name.sln" | Out-Default } "Error restoring $name"
NuGet restore

NuGet basics

The definitive documentation is nuget.org.
If you are a console person and don’t like nody UI stuff, you can use the Package Manager Console.

I am a NuGet user, most of the time, but once in a while, publish a package for my work and personal projects.

To prepare for package creation

Of course, download NuGet.exe, and make sure NuGet.exe is in your path.

Also, you need to register with nuget.org to get your api key, if you plan to share your package.

NuGet Update -self
NuGet SetApiKey Your-API-Key

Creating a package

If your package would simply contain a single assembly, you can create the package from an assembly. Otherwise, you would usually create it from a project, in which you can also benefit from tokenisation.

This creates a special nuspec file with tokens, to be replaced based on the project metaday.

Tokens

  • $id$: The Assembly name
  • $version$: The assembly version as specified in the assembly’s AssemblyVersionAttribute.
  • $author$: The company as specified in the AssemblyCompanyAttribute.
  • $description$: The description as specified in the AssemblyDescriptionAttribute.

In the folder where the csproj file, run:

nuget spec
nuget pack MyProject.csproj -Prop Configuration=Release

nuget spec will generate a spec file with basic metadata.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2012</copyright>
    <tags>Tag1 Tag2</tags>
  </metadata>
</package>

Once nuspec is ready, run nuget pack.
However, NuGet use the default build configuration set in the project file, and if you are a dev like me, it will be typically Debug. You wouldn’t want to publish your assembly built in Debug. so make sure to use Configuration option.

You would want to check the package you created to make sure everything necessary in there. Download NuGet Package Explorer and verify it.

Then publish it.

Add dependent assemblies to the package

Your project will have dependent assemblies (dlls), and want to include them in the package. If the dlls are references via NuGet, use . Otherwise, they are manually added, so use

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2012</copyright>
    <tags>Tag1 Tag2</tags>
    <dependencies>
        <dependency id="Hl.Local" version="[1.0.0.51]" />
        <dependency id="Hl.Valid" version="[1.0.0.50]" />
    </dependencies>
  </metadata>
  <files>
    <file src="..\lib\Hl.Frame.dll" target="lib\net35" />
  </files>

</package>

In dependency, if you use “[VERSION NO.]”, it will look for the exact version.

use a custom assemblyinfo from build server

You want to increase the version number from the build. Then you will need to update assemblyinfo before build the project. Then nuget package will have the verion number like Common.Framework.1.0.0.9.nupkg. Unfortunately, you have to use a custom build script, something like this. (it’s a psake script)

task BuildSolution -depends AssemblyInfo {
	Message("Building version $version")
	Exec { msbuild.exe "$slnFile" /t:Clean /t:Build /p:Configuration=$buildType /v:m /nologo }

task AssemblyInfo -depends Init {
	Update-AssemblyInfo -company "$COMPANY_NAME" -copyright "$COPYRIGHT" -LiteralPath "$baseDir\CustomAssemblyInfo.cs" -AssemblyVersion $script:version
}

NuGet basics