28 Sep 2021
During my #100DaysOfUmbraco challenge I learned how to create packages in Umbraco v9.
So far I have created 2 packages for v9.
Our.Umbraco.UserToDos - A simple to do list user dashboard
Portfolio Starter Kit - A starter kit which installs doc types, data types, templates, views, partial views, content and media.
Both of these packages are installed as NuGet packages. In this post I will show you what is required to create a NuGet package out of an AppPlugin type package which doesn't have any .NET code. This post assumes you know how to create an AppPlugin package for Umbraco already, perhaps you are trying to port one over from v7 or v8.
Before you can develop Umbraco v9 sites you need to make sure you have downloaded the .NET 5 SDK first.
Install Umbraco v9
Here are some commands you can paste into the command line, it will install umbraco, create a database and install the default Umbraco starter kit for you.
# Ensure we have the latest Umbraco templates dotnet new -i Umbraco.Templates::9.0.0-rc004 # Create solution/project dotnet new sln --name MySolution dotnet new umbraco -n MyProject --friendly-name "Admin User" --email "[email protected]" --password "1234567890" --connection-string "Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1" -ce dotnet sln add MyProject dotnet add MyProject package Umbraco.TheStarterKit --prerelease # Run dotnet run --project MyProject
In the command line you will see a message telling your which url the site is running on.
Copy and paste that Url into your browser, or Ctrl + Click the Url if you are using Windows Terminal.
You can log into umbraco on the site using the login details in the connection string above.
Check that it is running and working.
Stop the site by pressing Ctrl + C in the command line.
Add your package folder to the App_Plugins folder in the root of the site.
Enter dotnet run in the command line again and when it is running visit the site in the browser.
Check that your package is working how it needs to. It should do if it is a v8 package that doesn't use any .NET code.
Create a new project in the solution which will be named the same as what you want your package to be called. This is the project which will be created as a NuGet package, not the web project.
This project should be created as a Class Library targeting .NET 5
It's a good idea to search NuGet to see if the name of your package is already taken.
Create an App_Plugins folder inside this project and paste in your package folder.
You could use gulp or something to detect changes to these files in the web project and to copy them over.
Your project file for this new project should look like this:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net472;net5.0</TargetFrameworks> </PropertyGroup> <PropertyGroup> <PackageId>Our.Umbraco.UserToDos</PackageId> <Version>1.0</Version> <PackageIconUrl>https://github.com/prjseal/Our.UmbracoUserToDos/blob/main/images/logo.png?raw=true</PackageIconUrl> <PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageProjectUrl>https://our.umbraco.com/packages/backoffice-extensions/ourumbracousertodos/</PackageProjectUrl> <PackageTags>Umbraco</PackageTags> <RepositoryUrl>https://github.com/prjseal/Our.UmbracoUserToDos</RepositoryUrl> <Description>A simple to do list user dashboard for Umbraco</Description> <PackageReleaseNotes> 1.0 - First Version </PackageReleaseNotes> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> <ContentTargetFolders>content</ContentTargetFolders> <PackageOutputPath>../../output</PackageOutputPath> <IncludeBuildOutput>false</IncludeBuildOutput> </PropertyGroup> <!-- package files --> <ItemGroup> <Content Include="App_Plugins\**\*.*"> <ExcludeFromSingleFile>true</ExcludeFromSingleFile> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </Content> <!-- target file to copy app_plugins in .netcore --> <None Include="build\**\*.*"> <Pack>True</Pack> <PackagePath>buildTransitive</PackagePath> </None> </ItemGroup> </Project>
Make sure you change everything to be relevant to your package, don't leave it pointing to the UserToDos package details.
The target frameworks setting means this package can be installed on v8 and v9.
<PropertyGroup> <TargetFrameworks>net472;net5.0</TargetFrameworks> </PropertyGroup
This line tells it not to include a dll.
This part tells it to include the App_Plugins folder contents.
<Content Include="App_Plugins\**\*.*"> <ExcludeFromSingleFile>true</ExcludeFromSingleFile> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </Content>
This part includes a build targets file in the package which contains the rules for copying the files over when the package is installed on v9.
<None Include="build\**\*.*"> <Pack>True</Pack> <PackagePath>buildTransitive</PackagePath> </None>
In the root of this project create another folder called build. Add a file in the build folder which is the same name as your .csproj file but instead of ending with .csproj change it to .targets
The contents of this file should be like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <UserToDosContentFilesPath>$(MSBuildThisFileDirectory)..\content\App_Plugins\UserToDos\**\*.*</UserToDosContentFilesPath> </PropertyGroup> <Target Name="CopyUserToDosAssets" BeforeTargets="Build"> <ItemGroup> <UserToDosContentFiles Include="$(UserToDosContentFilesPath)" /> </ItemGroup> <Message Text="Copying UserToDos files: $(UserToDosContentFilesPath) - #@(UserToDosContentFiles->Count()) files" Importance="high" /> <Copy SourceFiles="@(UserToDosContentFiles)" DestinationFiles="@(UserToDosContentFiles->'$(MSBuildProjectDirectory)\App_Plugins\UserToDos\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> </Target> <Target Name="ClearUserToDosAssets" BeforeTargets="Clean"> <ItemGroup> <UserToDosDir Include="$(MSBuildProjectDirectory)\App_Plugins\UserToDos\" /> </ItemGroup> <Message Text="Clear old UserToDos data" Importance="high" /> <RemoveDir Directories="@(UserToDosDir)" /> </Target> </Project>
You can do a find and replace to change UserToDos to whatever the name of package folder is in the App_Plugins folder.
e.g. If the folder for yours is App_Plugins\EditLink\ then you could find and replace UserToDos with EditLink
Now you have everything you need for your package.
You can go to the command line again and run
This will create a NuGet package for you in the output folder which should be in the folder where your solution file is