Create your own Nuget for Xamarin.Forms

Do you have ever asked yourself how to create a NuGet package for your awesome components or services you’ve created? If so you don’t have to look further! In this post, I will show you how you can create a template project so you can create your own NuGets for Xamarin.Forms! ūüí™

Note

James Montemagno has already created an¬†extension¬†for Visual Studio (only available for Windows) with which you can create a NuGet for xamarin.forms. However, when I’m trying to use this extension visual studio stop working and do not respond at all. So if you do have the same problem with it¬†or¬†just want to learn how to create a template project by your own, just keep reading ūüėČ

If you don’t want to know how to create a project template and just want to use it, you can find the source code¬†here¬†and the finished template¬†here. Just clone or download it and add the zip file to the templates folder located in C:\\Users\Username\Documents\Visual Studio X\Templates\.

NuGet

First things first, I know you’re eager to start coding but at first, we should start with some basic theory about NuGets.

What is a NuGet

As a developer, you need some kind of mechanism through which you can share or consume code. This is especially helpful if you don’t want to write duplicate code or have to reinvent things other developers have already done.
To reuse code, you don’t want to have to include individual code files (compiled as .DLL), dependencies or other resources separately. So all these files will be bundled to a single package that can be easily shared.
For .NET the Microsoft-supported mechanism to share such packages is called NuGet. A NuGet defines how these packages for .NET are created, hosted and consumed.

Nuget for Xamarin.Forms

A NuGet package for Xamarin.Forms is a bit different than a default .netstandard NuGet package. This is because of default Xamarin.Forms project consists of at least three projects, each of which addresses a different platform. This means that our NuGet has to support at least each of these three (.netstandard, ios, android) platforms to be compatible with our Xamarin.Forms project.

Creating a project template

To create a NuGet that is compatible with multiple frameworks, we need to modify the .csproj file. To not always have to change the project file we’re going to create a template for a Xamarin.Froms NuGet project.

Create a new Project

So finally let’s get started!
To create our NuGet template fire up Visual Studio and create a new .NETStandard class library.

First, we delete the Class1 file that is created by default.
Then we are going to edit the csproj file. To do so right-click the project folder and select “Edit Project File”.

The .csproj file tells the compiler for what platform the project should be built and which files should be included. It also specifies SDK that should be used for the project and defines the metadata. If you want to learn more about the project file and it’s structure take a look at the official¬†Microsoft¬†site.

Add multiple frameworks

The first thing we need to do to support multiple targets flawlessly is to change the current SDK of the project. To do so you have to change the project SDK to MSBuild.Sdk.Extras/2.0.41

<Project Sdk="MSBuild.Sdk.Extras/2.0.41">
...
</Project>

If you have changed the SDK version we can continue to modify the property group section. This section specifies which frameworks the project will be built for and defines the metadata. Because we are going to create a template we have to be careful which metadata we are going to hardcode. Fortunately, Microsoft offers a mechanism called build parameters so we don’t have to hardcode these critical values. These parameters will be replaced by the actual values when you create a new project using this template. To get a list of all params that are available take a look at the¬†Microsoft site.

That’s how our finished property group will look like:

<Project Sdk="MSBuild.Sdk.Extras/2.0.41">

  <PropertyGroup>
    <TargetFrameworks>xamarin.ios10;monoandroid90;netstandard2.0</TargetFrameworks>

    <!-- other frameworks you can use-->
    <!--xamarin.mac20;xamarin.tvos10;xamarin.watchos10;monoandroid10.0;tizen40;netcoreapp2.1;netcoreapp3.1;net461-->

    <!-- Set project metadata -->
    <Company>FILL IN</Company>
    <Copyright>Copyright © FILL IN</Copyright>
    <RepositoryUrl>FILL IN</RepositoryUrl>
    <Authors>FILL IN</Authors>
    <Owners>FILL IN</Owners>
    <PackageReleaseNotes />
    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <RepositoryType>git</RepositoryType>
    <Product>$safeprojectname$ (netstandard2.0)</Product>
    <NeutralLanguage>en</NeutralLanguage>

    <Platform>AnyCPU</Platform>
    <DebugType>portable</DebugType>
    <PackageId>$safeprojectname$</PackageId>
    <AssemblyName>$safeprojectname$</AssemblyName>
    <RootNamespace>$safeprojectname$</RootNamespace>

    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
    <DebugType>portable</DebugType>

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

What exactly happened in the code above?

The most important change is the renaming of the first node in the property group. To support multiple frameworks we need to change the node from TargetFramework to TargetFrameworks. The value of this node specifies all frameworks we are going to support. For a default Xamarin.Forms application we should support at least Xamarin.iOS, MonoAndroid and .NETStandard (you have to provide a minimum supported version for every framework). 
To add additional frameworks just add them to the value of this node

The remaining properties specify the metadata of the project. You may have noticed the $safeprojectname$ value set for a bunch of properties. This is one of the built parameters I mentioned earlier. It sets the values of these nodes to the project name the user enters when creating a new project. Every node with “FILL IN” as value is just a placeholder and the user has to config these values later in the project settings.

Property groups with conditions

In Addition to our main property group, we will add a property group for the Debug and Release config. With these two different property groups, we can decide what happens when the package is built with debug and release configuration.
Just add this to your actual .csproj file:

...
  <!-- If config is debug create debug symbols -->
  <PropertyGroup Condition=" '$(Configuration)'=='Debug' ">
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

  <!-- If config is release create a package -->
  <PropertyGroup Condition=" '$(Configuration)'=='Release' ">
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>

    <!-- sourcelink: Include PDB in the built .nupkg -->
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
  </PropertyGroup>
 ...

With the above code, we tell the project that when we built in Debug mode it should also generate the debug symbols. When we build in Release mode we also want to generate a package (NuGet) and some documentation files for the project.
If you don’t want to include your .pdb files in the NuGet package you can remove the AllowedOutputExtensionsInPackageBuildOutputFolder node.

ItemGroups – Configuration for the different platforms

To build the NuGet for different platforms we have to tell the project which files are for which platform. Similar to a Xamarin.Forms application we will probably create platform-dependent files (like custom renderer). So we have to take care that the builder knows which files are meant for which platform. To do this we can create different ItemGroups. Each group will take care of a specific platform. Besides the different platforms (iOS, Android, …) we also have a shared code basis that is included in every platform.
So we will need to configure a default ItemGroup (shared project) and an ItemGroup for each platform we are going to support.

The code for the individual item groups will look like this:

  ...
  <!-- Create the item groups for the different platforms -->
  <ItemGroup>
    <!-- Include a folder for each platform -->
    <Folder Include="ios\" />
    <Folder Include="android\" />
    <Folder Include="standard\" />
    <Folder Include="shared\" />
    
    <Compile Include="shared\**\*.cs" />
    <None Include="readme.txt" pack="true" PackagePath="." />
    <PackageReference Include="Xamarin.Forms" Version="4.4.0.991265" />
  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
    <Compile Include="standard\**\*.standard.cs" />
  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('xamarin.ios')) ">
    <Compile Include="ios\**\*.ios.cs" />
  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('monoandroid')) ">
    <Compile Include="android\**\*.android.cs" />
  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('uwp')) ">
    <Compile Include="uap\**\*.uwp.cs" />
  </ItemGroup>
  ...

In the default item group, we will include all folders for the different platforms. These folders are not necessary but help us to structure the code and keep a better overview of the different platform implementations.

The structure of the code will look like the following:

So there is a separate folder for each platform where the platform implementations will be stored. As an additional readability feature, every file (except the shared files) will contain the platform in their names e.g. ScreenSize.ios.cs. This is enormously helpful when you have opened multiple files for a specific implementation and different platforms.

The task of the different ItemGroups is to include the correct files (the ones in the platform-specific folders) into the correct builds

Adding some additional item groups

If you want to create a template that supports virtually all platforms you can add this code:

  ...
  <!-- The item groups for the other framworks-->
  <!--
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.TVOS')) ">
    <Compile Include="tv\**\*.tv.cs" />
  </ItemGroup>-->

  <!--
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.WatchOS')) ">
    <Compile Include="watch\**\*.watch.cs" />
  </ItemGroup>
  -->

  <!--
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac')) ">
    <Compile Include="mac\**\*.mac.cs" />
  </ItemGroup>
  -->

  <!--
  <ItemGroup Condition=" $(TargetFramework.StartsWith('netcoreapp')) ">
    <Compile Include="core\**\*.core.cs" />
  </ItemGroup>
  -->

  <!--
  <ItemGroup Condition=" $(TargetFramework.StartsWith('Tizen')) ">
    <Compile Include="tizen\**\*.tizen.cs" />
    <PackageReference Include="Tizen.NET" Version="4.0.0" />
  </ItemGroup>
  -->
  ...

Now you just have to add the new framework you want to support to the TargetFrameworks and uncomment the corresponding ItemGroup.

Create a Template

So, now we are ready to create a template from our project. This is super easy in visual studio!

  • In the configured project click Project (menu bar) -> Export Template…
  • In the Export Wizard select “Project Template” and click Next.
  • Enter a name and a description for the template
  • (optional) If you want you can provide an icon and image for your template
  • Click Finish

Visual Studio 2019 and custom templates

If you are using visual studio 2019 and also have problems with it to find your template it’s likely because of the flat project hierarchy change from vs17 to vs19.

Modify the *.vstemplate file

To solve this issue you have to add some additional properties to your .vstmplate file.

  • Go to C:\Users\Username\Documents\Visual Studio 2019\My Exported Templates
  • Open your template *.zip
  • Edit the .vstemplate file inside the zip
  • Add the following lines inside the TemplateData node
    <LanguageTag>CSharp</LanguageTag>
    <PlatformTag>all</PlatformTag>
    <ProjectTypeTag>mobile</ProjectTypeTag>
  • Save the file
  • Copy the zip and replace the one under C:\Users\Username\Documents\Visual Studio 2019\Templates\ProjectTemplates\
  • Restart visual studio
  • Now visual studio should be able to find your template

Use your template!

Congrats, you have created your own visual studio project template! ūüéČ
Now you just have to restart visual studio and you should see your template.

You can find the entire code on GitHub.

11 thoughts on “Create your own Nuget for Xamarin.Forms

  1. Wow, marvelous weblog format! How long have you ever been running
    a blog for? you made running a blog glance easy.
    The entire glance of your website is excellent, let alone the content material!

  2. Hello There. I found your blog using msn. This is an extremely well written article.
    I’ll be sure to bookmark it and come back to read more of your useful info.
    Thanks for the post. I will definitely comeback.

  3. Hi there! Someone in my Facebook group shared this
    site with us so I came to look it over. I’m definitely enjoying the
    information. I’m book-marking and will be tweeting this to my followers!
    Terrific blog and superb style and design.

  4. Hey there, I think your website might be having browser compatibility issues.
    When I look at your blog in Chrome, it looks fine
    but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that, amazing blog!

  5. Cool blog! Is your theme custom made or did you download it from
    somewhere? A design like yours with a few simple
    adjustements would really make my blog shine.
    Please let me know where you got your design. With thanks

  6. What’s up mates, how is everything, and what you want to say about this
    paragraph, in my view its really amazing in support of me.

  7. Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically
    tweet my newest twitter updates. I’ve been looking for a plug-in like this for quite some time and was
    hoping maybe you would have some experience with something like this.
    Please let me know if you run into anything. I truly enjoy
    reading your blog and I look forward to your new updates.

  8. Very quickly this web site will be famous amid all blog viewers, due to it’s good articles or reviews

  9. Hello, I enjoy reading all of your article. I like to write a little comment to support you.

  10. Quality articles is the crucial to be a focus
    for the visitors to pay a quick visit the website, that’s what this web site is providing.

  11. Do you want to see me?:) https://katty.page.link/cnGv

    Hi. I’m love suks big dick. My profile here
    https://dsho.page.link/DWFC

Leave a Reply

Your email address will not be published. Required fields are marked *