Developer forum

Forum » Development » Locally installing NuGet package

Locally installing NuGet package

Justin Sjouw Dynamicweb Employee
Justin Sjouw
Reply

Hi, 

I'm having some trouble installing a (custom) nuget package.  I've attached both the zipped project and the package.

  • Files in the package in contentFiles\any\any\ do not seem to get installed into the files directory
  • The package installs correctly, but in the App Store selecting in from the "Installed Apps" list results in an error with a null reference on version

This is the first time I'm attempting this so a push in the right direction would be much appreciated :-)

Thanks,

Justin


Replies

 
Justin Sjouw Dynamicweb Employee
Justin Sjouw
Reply

I someone could try and install the package to see if the behaviour is the same, I would highly appreciate it :-)

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

From Chatgpt:

I had a close look at your project file and the behavior you describe, and a couple of things stand out that might explain both the missing files and the null reference on version.


1. contentFiles in NuGet is tricky

In .NET Core / .NET 8, contentFiles doesn’t behave the same way as the old content folder did in NuGet.

  • contentFiles is meant for source files or assets that get included into a project when it references your package.

  • But in your case, Dynamicweb’s app system expects physical files under /Files in the application root, not just entries in the consuming project’s build. NuGet doesn’t automatically copy them to your Dynamicweb instance.

That explains why you see the package install correctly but no files show up in Files.

Fix: You’ll probably want to package them as content (legacy style) or use a targets file inside the NuGet package to copy them at install-time to the Files folder. With contentFiles alone, nothing will land in your Dynamicweb /Files.


2. Null reference on version in “Installed Apps”

Dynamicweb’s App Store integration looks at the package metadata (<Version> and nuspec info).

  • You have <VersionPrefix> and some conditional <Version> properties, but note: NuGet will only use the evaluated <Version> at pack time. If that doesn’t resolve correctly, the .nuspec might end up with an empty <version/>.

  • If the version is missing, Dynamicweb will throw a null reference when trying to display it in Installed Apps.

Try forcing a simple static version to confirm:

<PropertyGroup>
  <Version>1.0.0</Version>
</PropertyGroup>

Build and repack. If the error disappears, your version condition logic was the culprit.


3. Small details in your .csproj

  • <PackageCopyToOutput> is not a valid MSBuild property in this context. The correct way is <CopyToOutputDirectory>Always</CopyToOutputDirectory> or PreserveNewest.

  • <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> is rarely needed in modern SDK-style projects. It can be dropped unless you’re debugging dependency resolution.

  • <FrameworkReference Include="Microsoft.AspNetCore.App" /> is redundant with net8.0. It doesn’t hurt, but you don’t need it.


Recommended adjustments

Try this in your .csproj:

<ItemGroup>
  <!-- Include all Files folder content in the NuGet package -->
  <Content Include="Files\**\*.*" Pack="true" PackagePath="content\Files\%(RecursiveDir)%(Filename)%(Extension)">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

<PropertyGroup>
  <!-- Simple explicit version for testing -->
  <Version>1.0.0</Version>
</PropertyGroup>

Notice the difference:

  • PackagePath="content\Files\..." instead of contentFiles.

  • Explicit version.

Then repack and reinstall.


Why this matters for Dynamicweb apps

Dynamicweb’s “Installed Apps” list isn’t just NuGet—it’s reading from its own app system layered on top. It expects:

  • A proper version number in the NuGet metadata.

  • Files physically in /Files after installation.

NuGet’s modern contentFiles won’t do that for you, so you need either:

  • Old-school content\ packaging, or

  • A .targets file to copy things where you need them on install.


If you want, I can sketch a .targets file that copies your Files contents into wwwroot/Files (or Dynamicweb’s Files folder) automatically when the NuGet is installed. Would you like me to?

YES!

 

Perfect, let’s wire this up properly.
The trick is: a .targets file inside your NuGet package can hook into the build of the consuming project and copy your Files folder into Dynamicweb’s /Files folder.

Here’s how you can do it:


1. Add a .targets file to your project

Create a file called MarkdownToolkit.targets (name it after your package) in your project root:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="CopyMarkdownToolkitFiles" AfterTargets="Build">
    <!-- Source: content files inside the package -->
    <ItemGroup>
      <MarkdownToolkitFiles Include="$(MSBuildThisFileDirectory)..\content\Files\**\*.*" />
    </ItemGroup>

    <!-- Destination: Dynamicweb's Files folder -->
    <Copy 
      SourceFiles="@(MarkdownToolkitFiles)" 
      DestinationFolder="$(MSBuildProjectDirectory)\Files\%(RecursiveDir)" 
      SkipUnchangedFiles="true" />
  </Target>
</Project>

This says:

  • After build, take everything from the NuGet package’s content\Files directory.

  • Copy it into the consuming project’s /Files folder.


2. Include this .targets file in your NuGet package

Update your .csproj so it packs the .targets file correctly:

<ItemGroup>
  <None Include="MarkdownToolkit.targets" Pack="true" PackagePath="build\MarkdownToolkit.targets" />
</ItemGroup>

Now, when someone installs your NuGet, MSBuild will import your .targets automatically.


3. Keep your Files folder packaging clean

Instead of contentFiles, switch back to content:

<ItemGroup>
  <Content Include="Files\**\*.*" Pack="true" PackagePath="content\Files\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>

That way, NuGet places your files under content/Files in the .nupkg, and the .targets file will copy them into the Dynamicweb solution’s /Files.


4. Test the flow

  • Build your package (dotnet pack).

  • Install it into your Dynamicweb 10 project.

  • Rebuild the solution.

You should see your files appear in Files\ in the consuming Dynamicweb site, and the Installed Apps view should now display the correct version (after fixing the <Version> property as I mentioned earlier).


This approach is pretty standard for packages that need to drop “physical assets” into a web project (like JS, CSS, or, in your case, app files).

Do you want me to also show you a minimal nuspec override that ensures Dynamicweb sees the correct metadata (version, description, etc.), so you can avoid the null reference issue altogether?

 
Justin Sjouw Dynamicweb Employee
Justin Sjouw
Reply

Thanks NicolAI! Unfortunately ChatGPT was basically wrong about everything, but it did help me forward ;-)

Turns out the null reference actually came from referencing DW ring1 like this apparently: <PackageReference Include="Dynamicweb.Suite.Ring1" Version="*" />

Changed that to a specific version : <PackageReference Include="Dynamicweb.Suite" Version="10.18.10" /> Which fixed it.

I still cannot get my files in the right place. If I pack the files like this, I end up with the files inside the Files folder under assets.

<Content Include="Files\**\*.*" Pack="true" PackagePath="Files/%(RecursiveDir)%(Filename)%(Extension)">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

If I remove Files, the files are like below in the nupkg, but not added in the corresponding folders (System\Items and Templates\etc...):

<Content Include="Files\**\*.*" Pack="true" PackagePath="%(RecursiveDir)%(Filename)%(Extension)">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

 

 

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Did you try

<Content Include="Files\**\*.*" Pack="true" PackagePath="contentFiles/%(RecursiveDir)%(Filename)%(Extension)">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 </Content>

Also the resulting nuget package should not reference ring1. You custom solution should have 2 projects - a runner/program.cs that references the ring1 and then your actual package that only references what you need.

 
 
Justin Sjouw Dynamicweb Employee
Justin Sjouw
Reply

Yes I tried that, and a couple of others structures mentioned before. when I have Sytem and Templates as a subfolder of contentFiles in the package, they do not get copied.

Long story short I cannot get Items and Templates to install to the correct location. 

The other issues are solved.

 
Justin Sjouw Dynamicweb Employee
Justin Sjouw
Reply

Any thoughts? I do have one, which is to add some more logging to the commandlog when installing apps. Right now, I was hoping to at least see the nuget package that get installed, and maybe even the files that get copied as part of the process. But the log now does not show much:

 

You must be logged in to post in the forum