Yeah its a bit of a pain and you will be pleased to learn there is more than one way to do it !
1 . With .target files
the 'traditional' v9/10 way is to use a .target file in your package that copies files from your nuget package to the site when someone runs a build (dontnet build or dotnet run)
this is a little painful but allows you to say, "copy all of these files to the site now please."
Tips here - the .targets file has to have the same name as the package (e.g for our.umbraco.superpackage the target is our.umbraco.superpackage.targets).
2. with a Razor class library
the hip and trendy way is to use a Razor Class Library. (RCL) an RCL is Microsoft's very-similar-but-not-quite-the-same way of getting files into a solution. It handles some of the .targets stuff for you.
and either better or more confusingly dependning on which way you look at it, it doesn't actually copy all the files to the soluition rather it references them directly in the nuget file, so people don't see the files in the solution but their site serves them up
there are a couple of fiddly bits if you use an RCL in Umbraco 10 (in the blog post) - but this is the way its going and in v11 its easier (e.g it will read your package.manifest from the RCL)
I have been following your posts, but am missing something somewhere, it is mostly working, but seems to miss some files and I have no idea why.
I think I am confusing the two different methods and something isn't quite working. I need an App_Plugins folder and files in the wwwroot folder and I think this is where I am getting very confused, I either get one or the other but not both.
NuGet was designed for class libraries. So adding all kinds of frontend stuff feels a bit hacky, even when following the official way to do it. The choices I make are:
I always create a Razor class library now. It's excellent in hiding files that should not be edited by the author of a project. Think of views or view components.
By default, files from packages are kept in the package folder and are not copied to the project that uses that package. However, sometimes you need files from the NuGet to be present in your solution for various reasons. For Umbraco the App_Plugins files need to be there to be loaded correctly, but in my case I also have some sass-files or javascript files that I want to include in a larger bundle/compilation.
By default, if you use the dotnet template from Umbraco for creating packages, it will include a targets file, like Kevin mentioned. This targets file is setup to copy all file from App_Plugins in the package to the local project that uses the package. I usually append to that for the sass and script files that I want copied.
I also have in rare cases another kind of file: a file that needs to be only copied to the local project once if it doesn't exist yet. I use this in a kind of base package/base starter kit. My package includes files like the _Layout.cshtml and a head.cshtml. These files provide a solid starting point, but are usually altered when in use. I also use the targets file to copy these files over, but with a condition that the files do not exist yet.
<!--
Copies views to the views folder. Does not override files
-->
<Target Name="CopyViews" BeforeTargets="Build">
<ItemGroup>
<ViewFiles Include="$(ViewsFolder)**\*.*" />
</ItemGroup>
<Message Text="Copying views from: $(ViewsFolder) - #@(ViewFiles->Count()) files" Importance="high" />
<Message Text="Copying views to: $(MSBuildProjectDirectory)\Views\" Importance="high" />
<Copy
SourceFiles="@(ViewFiles)"
DestinationFiles="@(ViewFiles->'$(MSBuildProjectDirectory)\Views\%(RecursiveDir)%(Filename)%(Extension)')"
Condition="!Exists('$(MSBuildProjectDirectory)\Views\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
Hope this gives some extra insights :) It's a bit annoying the first time, but once you get the hang of it, it's not that hard anymore!
What about things like doctypes/templates? That is where I'm struggling the most. I'm currently importing a package XML which works fine in 10 but I just can't get it working in 11
I haven't tested or workes with any packages in 11 yet, so I can't help you (yet). Maybe the package.xml structure was changed? I find that hard to believe though that that is the case. I'll let you know if I find out more.
I'm still going round in circles, I tried your views suggestion Luuk, but it doesn't copy any files, and although it says it copies the App_Plugins files I can't see them in the project (they are in the folder though), surely it shouldn't be this difficult!
Maybe more important: are the files present in the package? NuGet packages are pretty stupid because they are meant for class libraries. Adding (static) content files to a packages usually requires some effort.
I thought so ;) These are exactly all the problems I ran into when I created the first package. So reminder for next time: always check first what's actually in the package.
You need to edit the project file and and tell it to pack it. Here is my section, you can modify for your situation:
You'll see here that the App_Plugins folder was also set this way by Umbraco in their template. I think officially you're supposed to add static content in a certain folder in the package, but I just put them on the root to make life simple ;)
So far so good, however I now need to get the views registered as templates in the backoffice otherwise the documents do not pick them up.
If I use a package.Xml and use a migration Plan it overwrites the content of the views with the content from the package.Xml which I don't want, is there any way to either prevent that, or maybe register them as templates in code?
I am already running some code to create member types and groups, but never created a template definition in code.
I removed the templates from the package.zip and added the views back in the RCL, then in my PackageMigrationbase, I registered the views as templates prior to importing the package like this
protected override void Migrate()
{
//register the views as templates first
_fileService.CreateTemplateWithIdentity("ForumMaster", "forumMaster",null);
var master = _fileService.GetTemplate("forumMaster");
if (master != null)
{
var templatesToFind = new[] { "forum", "forumPost", "login", "members", "profile", "register", "reset", "verify", "searchPage" };
foreach (var template in templatesToFind)
{
_fileService.CreateTemplateWithIdentity(template.FirstCharToUpper(), template,null,master);
}
}
//Now the templates are registered we can import the package xml
ImportPackage.FromEmbeddedResource<ImportPackageXmlMigration>().Do();
Context.AddPostMigration<PublishRootBranchPostMigration>();
}
Mmm, that is currently what I'm doing, but the package.xml migration overwrites the views that are in the nuget package as it gets run afterwards, so may as well just get rid of the views from the nuget package and just use a package.xml file and migration plan which just seems a bit counter intuitive as you then need to keep both the package project and the site project which created the package.xml in sync
And I couldn't even get the migration plan working in Umraco 11, it just did nothing.
Oh well, will just keep digging, Thanks for your suggestions.
You are correct. I just tested it (in Umbraco 11) and the template file that came out of the NuGet package gets overridden when Umbraco starts and executes the migration. Never knew. Because it's practically an empty file I never noticed it. But in hindsight, we've had some issues where a certain file would sometimes be empty. This explains it.
Looking at the package.xml, it does indeed contain the content for the template file. I can't find any documentation about what's possible in the package.xml file. So I'm not sure if we can skip the creation of the physical file.
In my case, it's the template for the homepage, which by default is empty so we can start development. But it means that if a developer runs the project for the first time when development is already underway, the homepage template might be overridden by the one in the page. I'm gonna try to remove the design tag - which contains the template html - in the package.xml and see what happends :P
Well, My nuget package now installs fine in Umbraco 11 & 10 :)
I removed the template views from the nuget project but left the partial views, so now the package.xml takes care of creating the templates but the partial views get updated by the nuget package, so for now I am reasonably happy :D
Many thanks to both Luuk and Kevin for your assistance on this, I was beginning to tear out what little hair I have left :D
Exactly how I felt when I had to build the first package. However, it's much easier after the first time and you know the different parts that make it work.
Creating nuget package for Umbraco
Is there a decent set of instructions or examples of how to create a nuget package for Umbraco 10?
I'm just going round and round in circles trying to get everything to install correctly and am about to give up.
I need to include Views, an App_Plugin folder, css and scripts
It was so much simpler using the v8 packages, this is right PITA
Hi Huw,
Yeah its a bit of a pain and you will be pleased to learn there is more than one way to do it !
1 . With .target files
the 'traditional' v9/10 way is to use a
.target
file in your package that copies files from your nuget package to the site when someone runs a build (dontnet build or dotnet run)this is a little painful but allows you to say, "copy all of these files to the site now please."
As an example of that - this is the build file in the repo of one of my packages : https://github.com/KevinJump/Our.Umbraco.BackOfficeThemes/blob/shared/main/Our.Umbraco.BackOfficeThemes/buildTransitive/Our.Umbraco.BackOfficeThemes.targets
Tips here - the
.targets
file has to have the same name as the package (e.g for our.umbraco.superpackage the target isour.umbraco.superpackage.targets
).2. with a Razor class library
the hip and trendy way is to use a Razor Class Library. (RCL) an RCL is Microsoft's very-similar-but-not-quite-the-same way of getting files into a solution. It handles some of the .targets stuff for you.
and either better or more confusingly dependning on which way you look at it, it doesn't actually copy all the files to the soluition rather it references them directly in the nuget file, so people don't see the files in the solution but their site serves them up
I wrote a blog post or two about that way. ( https://dev.to/kevinjump/umbraco-10-razor-class-library-packages-pt1-3nfa )
there are a couple of fiddly bits if you use an RCL in Umbraco 10 (in the blog post) - but this is the way its going and in v11 its easier (e.g it will read your package.manifest from the RCL)
Hi Kevin,
I have been following your posts, but am missing something somewhere, it is mostly working, but seems to miss some files and I have no idea why.
I think I am confusing the two different methods and something isn't quite working. I need an App_Plugins folder and files in the wwwroot folder and I think this is where I am getting very confused, I either get one or the other but not both.
Screams very loudly!!
local nuget cache causing problems :D, getting somewhere now.
Thanks for the pointers Kevin, everything seems to be working now for Umbraco 10, I just need to get it sorted for v11 next :D
To add to Kevin's excellent answer:
NuGet was designed for class libraries. So adding all kinds of frontend stuff feels a bit hacky, even when following the official way to do it. The choices I make are:
I always create a Razor class library now. It's excellent in hiding files that should not be edited by the author of a project. Think of views or view components.
By default, files from packages are kept in the package folder and are not copied to the project that uses that package. However, sometimes you need files from the NuGet to be present in your solution for various reasons. For Umbraco the App_Plugins files need to be there to be loaded correctly, but in my case I also have some sass-files or javascript files that I want to include in a larger bundle/compilation.
By default, if you use the dotnet template from Umbraco for creating packages, it will include a targets file, like Kevin mentioned. This targets file is setup to copy all file from App_Plugins in the package to the local project that uses the package. I usually append to that for the sass and script files that I want copied.
I also have in rare cases another kind of file: a file that needs to be only copied to the local project once if it doesn't exist yet. I use this in a kind of base package/base starter kit. My package includes files like the _Layout.cshtml and a head.cshtml. These files provide a solid starting point, but are usually altered when in use. I also use the targets file to copy these files over, but with a condition that the files do not exist yet.
Hope this gives some extra insights :) It's a bit annoying the first time, but once you get the hang of it, it's not that hard anymore!
What about things like doctypes/templates? That is where I'm struggling the most. I'm currently importing a package XML which works fine in 10 but I just can't get it working in 11
I haven't tested or workes with any packages in 11 yet, so I can't help you (yet). Maybe the package.xml structure was changed? I find that hard to believe though that that is the case. I'll let you know if I find out more.
I don't think it has, but I will manually create some stuff in a vanilla 11 and create the package xml in that to do a compare
I'm still going round in circles, I tried your views suggestion Luuk, but it doesn't copy any files, and although it says it copies the App_Plugins files I can't see them in the project (they are in the folder though), surely it shouldn't be this difficult!
Maybe more important: are the files present in the package? NuGet packages are pretty stupid because they are meant for class libraries. Adding (static) content files to a packages usually requires some effort.
Mmm, no they aren't :( the App_Plugins folder is, just not the views
I thought so ;) These are exactly all the problems I ran into when I created the first package. So reminder for next time: always check first what's actually in the package.
You need to edit the project file and and tell it to pack it. Here is my section, you can modify for your situation:
You'll see here that the App_Plugins folder was also set this way by Umbraco in their template. I think officially you're supposed to add static content in a certain folder in the package, but I just put them on the root to make life simple ;)
mmm, If I do that I get an error about Duplicate content items and it won't build
If I manually add them in the nuget package file, it all works, so just need to figure out how to get them in :D
Bezinga!
I think I've cracked it :)
I had to do it like this
So far so good, however I now need to get the views registered as templates in the backoffice otherwise the documents do not pick them up.
If I use a package.Xml and use a migration Plan it overwrites the content of the views with the content from the package.Xml which I don't want, is there any way to either prevent that, or maybe register them as templates in code?
I am already running some code to create member types and groups, but never created a template definition in code.
I managed to work out how to do this.
I removed the templates from the package.zip and added the views back in the RCL, then in my PackageMigrationbase, I registered the views as templates prior to importing the package like this
Nice! I might implement this as well :)
Mmm, doesn't seem to be that reliable :( I installed an updated package version and it removed the templates from the doctypes!
Doh! ignore my last comment it was me being an idiot :D
Uhm as far as I know I don't do anything special with the templates. I added them in the package.xml and I add the files the way you're doing now.
Mmm, that is currently what I'm doing, but the package.xml migration overwrites the views that are in the nuget package as it gets run afterwards, so may as well just get rid of the views from the nuget package and just use a package.xml file and migration plan which just seems a bit counter intuitive as you then need to keep both the package project and the site project which created the package.xml in sync
And I couldn't even get the migration plan working in Umraco 11, it just did nothing.
Oh well, will just keep digging, Thanks for your suggestions.
You are correct. I just tested it (in Umbraco 11) and the template file that came out of the NuGet package gets overridden when Umbraco starts and executes the migration. Never knew. Because it's practically an empty file I never noticed it. But in hindsight, we've had some issues where a certain file would sometimes be empty. This explains it.
Looking at the package.xml, it does indeed contain the content for the template file. I can't find any documentation about what's possible in the package.xml file. So I'm not sure if we can skip the creation of the physical file.
In my case, it's the template for the homepage, which by default is empty so we can start development. But it means that if a developer runs the project for the first time when development is already underway, the homepage template might be overridden by the one in the page. I'm gonna try to remove the design tag - which contains the template html - in the package.xml and see what happends :P
It the templates are not in the xml then Umbraco does not see the views and all the pages have no template :)
Yeah I know, made an error in my previous post. I want to try to remove only the section of the template that contains the html.
If you do that it creates an empty view which overwrites the ones in the package, I already tried that :D
I created a separate topic with this question to keep things clean :)
https://our.umbraco.com/forum/using-umbraco-and-getting-started//110666-migration-with-templates-only-override-physical-file-if-it-doesnt-exist
Well, My nuget package now installs fine in Umbraco 11 & 10 :)
I removed the template views from the nuget project but left the partial views, so now the package.xml takes care of creating the templates but the partial views get updated by the nuget package, so for now I am reasonably happy :D
Many thanks to both Luuk and Kevin for your assistance on this, I was beginning to tear out what little hair I have left :D
Exactly how I felt when I had to build the first package. However, it's much easier after the first time and you know the different parts that make it work.
Glad to be able to help :)
is working on a reply...