c

Creating and publishing nuget packages

Ever since the initial release of Nuget Package Manager in 2010 its helped thousands of .NET developers easily integrate third party libraries into their existing project. It has also helped reduce “DLL hell”. But how do you create one of these packages and publish it to Nuget.org or a private nuget server?

It’s actually very easy. Lets start with a simple real world project.

I have a simple c# solution called “SampleNugetLib” that contains two projects: (C# class library called “SampleNugetLib” and a Test project called “SampleNugetLib.Tests”), our goals are:

  1. Use MSBuild to compile the C# library.
  2. Create/publish nuget package.

 

Download

Download Sample Project

Make sure to grab a copy of the sample project from my github repo so you can follow along.

Download

Use MSBuild to compile the C# library

Open the file src/_build/build.proj. This is your basic Visual Studio project file. This file was created specifically for compiling and publishing our nuget package. With a help of a powershell script we can create and pass in the parameters such as the solution name, nuget api key and build mode to decouple ourselves from the vs project file.

Everything starts in the root, open the file src/build.ps1, this is your basic powershell script, this will be the file that we execute to get everything started.

Here is the contents of this file:

$project_name = 'SampleNugetLib'
$solution_name = 'SampleNugetLib.sln'
$nuget_packageVersion = '1.0.1'
$nuget_packageName = 'SampleNugetLib'
$nuget_apikey = 'YOUR_API_KEY'
$nuget_server = 'https://www.nuget.org/api/v2/package'
$build_mode = 'Release' 

if(!$build_mode){
    Write-Error "Cannot find build mode"
}else{
	# Run MSBuild
	msbuild.exe _build\build.proj `
	    /p:Build_Number=$version `
	    /p:Environment=$env `
	    /p:ProjectName=$project_name `
	    /p:SolutionName=$solution_name `
	    /p:NugetApiKey=$nuget_apikey `
	    /p:NugetServer=$nuget_server `
	    /p:NugetPackageName=$nuget_packageName `
	    /p:NugetPackageVersion=$nuget_packageVersion `
	    /p:ProjectBuildMode=$build_mode `
	    /ToolsVersion:12.0
}

As you can see we are simply passing along project file and some parameters for msbuild.

Take note: You will need your own API Key ($nuget_apikey), and a unique name for the nuget package ($nuget_packageName) because “SampleNugetLib” already exists under my nuget.org account (https://www.nuget.org/packages/SampleNugetLib).

 

Create/publish nuget package

Now lets take a closer look at what is going on in src/_build/build.proj. At first glance you can see a property group for all the parameters we are passing in:

  <PropertyGroup>
    <Root>$(MSBuildStartupDirectory)</Root>
    <nugetexe>$(Root)\_build\lib\nuget\nuget.exe</nugetexe>
    <ProjectBuildMode></ProjectBuildMode>
    <NuGetPackageVersion></NuGetPackageVersion>
    <ProjectName></ProjectName>
    <SolutionName></SolutionName>
    <VisualStudioVersion>12.0</VisualStudioVersion>
    <NugetApiKey></NugetApiKey>
    <NugetServer></NugetServer>
    <NugetPackageName></NugetPackageName>
  </PropertyGroup>

Easy enough right? Lets take a look at the target that actually creates the nuget package:

We have a nuget spec file already created at src/_build/BaseNugetSpec.nuspec this contains all the meta data about the nuget package, take a look at the files node, we are including a file called “SampleNugetLib.dll”, lets take a look at the msbuild project to see how it all comes together:

  <Target Name="Clean">
    <!-- Clean up -->
    <ItemGroup>
      <FilesToDelete Include="$(Root)\_build\Published\**\*.*" />
      <FilesToDelete Include="$(Root)\_build\Artifacts\**\*.*" />
    </ItemGroup>
    <Delete Files="@(FilesToDelete)" ContinueOnError="true" />

    <!-- Ensure directories exists -->
    <MakeDir Directories="$(MSBuildProjectDirectory)\Artifacts" Condition="!Exists('$(MSBuildProjectDirectory)\Artifacts')" />
    <MakeDir Directories="$(MSBuildProjectDirectory)\Published" Condition="!Exists('$(MSBuildProjectDirectory)\Published')" />
  </Target>

  <Target Name="DebugInfo" DependsOnTargets="Clean" AfterTargets="Clean">
    
    <!-- Diagnostics -->
    <Message Text="Diagnostics:"/>
    <Message Text="Project Build Mode:    $(ProjectBuildMode)" />
    <Message Text="Solution Name:    $(SolutionName)" />
    <Message Text="Project Name:    $(ProjectName)" />
    <Message Text="Build dir:       $(MSBuildProjectDirectory)" />
    <Message Text="Project root:    $(Root)" />
    <Message Text="Nuget Api Key:   $(NugetApiKey)" />
    <Message Text="Nuget Server Url:   $(NugetServer)" />
    <Message Text="Nuget Package Name:   $(NugetPackageName)" />
    <Message Text="Nuget Package Version:   $(NuGetPackageVersion)" />
  </Target>

  <Target Name="BuildSolution" DependsOnTargets="DebugInfo" AfterTargets="DebugInfo">
    <!-- Restore Nuget Packages -->
    <Message Text="Restoring nuget..."/>
    <Exec Command="$(nugetexe) restore $(Root)\$(SolutionName)" />

    <!-- Compile -->
    <ItemGroup>
      <ProjectToBuild Include="$(Root)\$(SolutionName)" />
    </ItemGroup>
    <MSBuild Projects="@(ProjectToBuild)" Targets="Build" Properties="VisualStudioVersion=$(VisualStudioVersion);Configuration=$(ProjectBuildMode);Platform=Any CPU;OutputPath=$(Root)\_build\Published">
      <Output TaskParameter="TargetOutputs" ItemName="AssembliesBuiltByChildProjects" />
    </MSBuild>
  </Target>
  <Target Name="Build" DependsOnTargets="BuildSolution" AfterTargets="BuildSolution">

    <!-- Add NuGet files-->    
    <ItemGroup>
      <NuSpecSourceFile Include="$(Root)\_build\BaseNugetSpec.nuspec" />
    </ItemGroup>
    <ItemGroup>
      <NuSpecDestinationFiles Include="$(Root)\_build\Published\$(NugetPackageName).nuspec" />
    </ItemGroup>
    <Copy SourceFiles="@(NuSpecSourceFile)" DestinationFiles="@(NuSpecDestinationFiles)"/>

    <!-- Replace version in nuspec file -->
    <FileUpdate Files="$(Root)\_build\Published\$(NugetPackageName).nuspec" Regex="0.0.0" ReplacementText="$(NuGetPackageVersion)" />
    <FileUpdate Files="$(Root)\_build\Published\$(NugetPackageName).nuspec" Regex="PID" ReplacementText="$(NugetPackageName)" />

    <!-- Run nuget pack -->
    <Exec Command="$(nugetexe) pack $(Root)\_build\Published\$(NugetPackageName).nuspec -o $(Root)\_build\Artifacts" />

    <!-- Run nuget push -->
    <Exec Command="$(nugetexe) push $(Root)\_build\Artifacts\$(NugetPackageName).$(NuGetPackageVersion).nupkg $(NugetApiKey) -Source $(NugetServer)" />
  </Target>
</Project>

This is somewhat self explanatory by looking at the target steps:

  • Delete two folders: “Published” and “Artifacts” – The publish folder should hold all your assembly files, the artifacts folder should hold the final file, in this case a nuget package.
  • Recreate these two folders
  • Display some diagnostics information
  • Restore nuget packages for the solution
  • Build the solution and set the output path to the published folder
  • Take a copy of the BaseNugetSpec.nuspec file and place it in the published folder, remember the files node we looked at earlier in the nuspec file? Well now this DLL should be in that published folder as well.
  • Call the “nuget pack” command line, this creates the nuget package (.nupkg)
  • Call the “nuget push” command line, this publishes the newly created nuget package to the nuget server specified in the powershell script.

For more documentation on nuget pack and push command lines take a look here: https://docs.nuget.org/consume/command-line-reference

Putting it all together

Ok now that we reviewed the process and code, lets execute the powershell script. Please make sure to have msbuild in your PATH variable, see this link for more information: http://stackoverflow.com/questions/6319274/how-do-i-run-msbuild-from-the-command-line-using-windows-sdk-7-1

Open up a windows powershell console, browse to the src folder and run the command:

.\build.ps1

Easy enough right? Please feel free to submit pull requests to make this code better. I am also available on twitter @tekguy

By |April 23rd, 2015|Coding|0 Comments

C# extension method to “prettyify” your xml output

Here is simple c# extension method to format your XML data. This is useful for logging xml data to trace files, etc:

public static class XmlDocumentPrettyExtension
{
    public static string Prettyify(this XmlDocument xmlDocument)
    {
        var stringWriter = new StringWriter(new StringBuilder());
        var xmlTextWriter = new XmlTextWriter(stringWriter) { Formatting = Formatting.Indented };
        xmlDocument.Save(xmlTextWriter);
        return stringWriter.ToString();
    }
}
By |November 10th, 2014|Coding|0 Comments

Get SqlConnection from DbContext

I’ve been using Entity Framework for sometime now. But we all know using EF for everything may not be the best option. I decided to use Dapper for certain db queries.

Dapper requires an open SqlConnection object, I didn’t want to have to manage another connection string in my web.config so I looked at options for converting an EF connection string to an ADO connection string.

After some research I came up with the following:

private SqlConnection GetSqlConnection(DbContext dbContext)
{
    var ec = dbContext.Database.Connection;
    var adoConnStr = ec.ConnectionString;
    return new SqlConnection(adoConnStr);
    
} 
By |October 23rd, 2014|Coding|0 Comments

Implementing VisibilityProvider in MvcSiteMapProvider

If you are coming from MvcSiteMapProvider version 3 you will notice some changes in version 4. One of the key changes in version 4 is using app setting key/values instead of the SiteMap node. To learn more about new features in version 4 click here.

Implementing a visibility provider in version 4 is simple. It requires a couple small steps:

  1. Creating a class and derive it from “SiteMapNodeVisibilityProviderBase”.
  2. Add a setting to your web.config file.
  3. Update the site map file.

 

Creating our visibility class

Configuring web.config

Take caution and matchup your namespaces and classes correctly with the sample code I provided. Add a new app setting key/value:

<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MyCompany.Web.MyCompanySiteMapVisibilityProvider, MyCompany.Web" />

Making adjustments to sitemap

Finally we are going to make some adjustments to our sitemap file, use the following node as an example, take note of the visibility attribute:

<mvcSiteMapNode title="My Page I want to hide" controller="Home" action="HidePage" visibility="false">

 

I hope this helps, if you have any questions please contact me on twitter: @tekguy

By |January 9th, 2014|Coding|0 Comments

c# datatypes and lengths…provides you with a visual representation of limits.

By |May 22nd, 2012|Coding|0 Comments

c# datatypes and lengths…provides you with a visual representation of limits.

By |May 22nd, 2012|Coding|0 Comments