Nuget

Use NuGets for your common Xamarin (Forms) code (and automate the creation process)

Use NuGets for your common Xamarin (Forms) code (and automate the creation process)

Internal libraries

Writing (or copy and pasting) the same code over and over again is one of those things I try to avoid when writing code. For quite some time, I already organize such code in libraries. Until last year, this required quite some work managing all libraries for each Xamarin platform I used. Luckily, the MSBuild SDK Extras extensions showed up and made everything a whole lot easier, especially after James Montemagno did a detailed explanation on how to get the most out of it for Xamarin plugins/libraries.

Getting started

Even if I repeat some of the steps of James’ post, I’ll start from scratch on the setup part here. I hope to make the whole process straight forward for everyone – that’s why I think it makes sense to show each and every step. Please make sure you are using the new .csproj type. If you need a refresh on that, you can check my post about migrating to it (if needed).

MSBuild.Sdk.Extras

The first step is pulling in MSBuild.Sdk.Extras, which will enable us to target multiple platforms in one single library. For this, we need a global.json file in the solution folder. Right click on the solution name and select ‘Open Folder in File Explorer‘, then just add a new text file and name it appropriately.

The next step is to define the version of the MSBuild.SDK.Extras library we want to use. The current version is 1.6.65, so let’s define it in the file. Just click the ‘Solution and Folders‘ button to find the file in Visual Studio:

switch to folder view

Add these lines into the file and save it:

{
  "msbuild-sdks": {
    "MSBuild.Sdk.Extras": "1.6.65"
  }
}

Modifying the project file

Switch back to the Solution view and right click on the .csproj file. Select ‘Edit [ProjectName].csproj‘. Let’s modify and add the project definitions. We’ll start right in the first line. Replace the first line to pull in the MSBuild.Sdk.Extras:

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

Next, we’re separating the Version tag. This will ensure that we’ll find it very quickly in future within the file:

  <!--separated for accessibility-->
  <PropertyGroup>
    <Version>1.0.0.0</Version>
  </PropertyGroup>

Now we are enabling multiple targets, in this case our Xamarin platforms. Please note that there are two separated versions – one that includes UWP and one that does not. I thought I would be fine to remove the non-UWP one if I include UWP and was precent with some strange build errors that where resolved only by re-adding the deleted line. I do not remember the reason, but I made a comment in my template to not remove it – so let’s just keep it that way.

  <!--make it multi-platform library!-->
  <PropertyGroup>
    <UseFullSemVerForNuGet>false</UseFullSemVerForNuGet>
    <!--we are handling compile items ourselves below with a custom naming scheme-->
    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
    <KEEP ALL THREE IF YOU ADD UWP!-->
    <TargetFrameworks></TargetFrameworks>
    <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;MonoAndroid81;Xamarin.iOS10;uap10.0.16299;</TargetFrameworks>
    <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;MonoAndroid81;Xamarin.iOS10;</TargetFrameworks>
  </PropertyGroup>

Now we will add some default NuGet packages into the project and make sure our file get included only on the correct platform. We follow a simple file naming scheme (Xamarin.Essentials uses the same):

[Class].[platform].cs

This way, we are able to add all platform specific code together with the shared entry point in a single folder. Let’ start with shared items. These will be available on all platforms listed in the PropertyGroup above:

  <!--shared items-->
  <ItemGroup>
    <!--keeping this one ensures everything goes smooth-->
    <PackageReference Include="MSBuild.Sdk.Extras" Version="1.6.65" PrivateAssets="All" />

    <!--most commonly used (by me)-->
    <PackageReference Include="Xamarin.Forms" Version="3.4.0.1029999" />
    <PackageReference Include="Xamarin.Essentials" Version="1.0.1" />

    <!--include content, exclude obj and bin folders-->
    <None Include="**\*.cs;**\*.xml;**\*.axml;**\*.png;**\*.xaml" Exclude="obj\**\*.*;bin\**\*.*;bin;obj" />
    <Compile Include="**\*.shared.cs" />
  </ItemGroup>

The ‘**\‘ part in the Include property of the Compile tag ensures MSBuild includes also classes in subfolders. Now let’s add some platform specific rules to the project:

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

  <ItemGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
    <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.1.9" />
    <Compile Include="**\*.uwp.cs" />
  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
    <!--need to reference all those libs to get latest minimum Android SDK version (requirement by Google)... #sigh-->
    <PackageReference Include="Xamarin.Android.Support.Annotations" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Compat" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.Palette" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Core.UI" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Media.Compat" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.RecyclerView" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Transition" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.1" />
    <PackageReference Include="Xamarin.Android.Support.Vector.Drawable" Version="28.0.0.1" />
    <Compile Include="**\*.android.cs" />
  </ItemGroup>

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

Two side notes:

  • Do not reference version 6.2.2 of the Microsoft.NETCore.UniversalWindowsPlatform NuGet. There seems to be bug in there that will lead to rejection of your app from the Microsoft Store. Just keep 6.1.9 (for the moment).
  • You may not need all of the Xamarin.Android packages, but there are a bunch of dependencies between them and others, so I decided to keep them all

If you have followed along, hit the save button and close the .csproj file. Verifying everything went well is pretty easy – your solution structure should look like this:

multi-targeting-project

Before we’ll have a look at the NuGet creation part of this post, let’s add some sample code. Just insert this into static partial classes with the appropriate naming scheme for every platform and edit the code to match the platform. The .shared version of this should be empty (for this sample).

     public static partial class Hello
    {
        public static string Name { get; set; }

        public static string Platform { get; set; }

        public static  void Print()
        {
            if (!string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Platform))
                System.Diagnostics.Debug.WriteLine($"Hello {Name} from {Platform}");
            else
                System.Diagnostics.Debug.WriteLine($"Hello unkown person from {Device.Android}");
        }
    }

Normally, this would be a Renderer or other platform specific code. You should get the idea.

Preparing NuGet package creation

We will now prepare our solution to automatically generate NuGet packages both for DEBUG and RELEASE configurations. Once the packages are created, we will push it to a local (or network) file folder, which serves as our local NuGet-Server. This will fit for most Indie-developers – which tend to not replicate a full blown enterprise infrastructure for their DevOps needs. I will also mention how you could push the packages to an internal NuGet server on a sideline (we are using a similar setup at work).

Adding NuGet Push configurations

One thing we want to make sure is that we are not going to push packages on every compilation of our library. That’s why we need to separate configurations. To add new configurations, open the Configuration Manager in Visual Studio:

In the Configuration Manager dialog, select the ‘<New…>‘ option from the ‘Active solution configuration‘ ComboBox:

Name the new config to fit your needs, I just use DebugNuget which will signal that we are pushing the NuGet package for distribution. I am copying the settings from the Debug configuration and let Visual Studio add the configurations to project files within the solution. Repeat the same for Release configuration.

The result should look like this:

Modifying the project file (again)

If you head over to your project file, you will see the Configurations tag has new entries:

  <PropertyGroup>
    <Configurations>Debug;Release;DebugNuget;ReleaseNuget</Configurations>
  </PropertyGroup>

Next, add the properties of your assembly and package:

    <!--assmebly properties-->
  <PropertyGroup>
    <AssemblyName>XamarinNugets</AssemblyName>
    <RootNamespace>XamarinNugets</RootNamespace>
    <Product>XamarinNugets</Product>
    <AssemblyVersion>$(Version)</AssemblyVersion>
    <AssemblyFileVersion>$(Version)</AssemblyFileVersion>
    <NeutralLanguage>en</NeutralLanguage>
    <LangVersion>7.1</LangVersion>
  </PropertyGroup>

  <!--nuget package properties-->
  <PropertyGroup>
    <PackageId>XamarinNugets</PackageId>
    <PackageLicenseUrl>https://github.com/MSiccDevXamarinNugets</PackageLicenseUrl>
    <PackageProjectUrl>https://github.com/MSiccDevXamarinNugets</PackageProjectUrl>
    <RepositoryUrl>https://github.com/MSiccDevXamarinNugets</RepositoryUrl>

    <PackageReleaseNotes>Xamarin Nugets sample package</PackageReleaseNotes>
    <PackageTags>xamarin, windows, ios, android, xamarin.forms, plugin</PackageTags>

    <Title>Xamarin Nugets</Title>
    <Summary>Xamarin Nugets sample package</Summary>
    <Description>Xamarin Nugets sample package</Description>

    <Owners>MSiccDev Software Development</Owners>
    <Authors>MSiccDev Software Development</Authors>
    <Copyright>MSiccDev Software Development</Copyright>
  </PropertyGroup>

Configuration specific properties

Now we will add some configuration specific PropertyGroups that control if a package will be created.

Debug and DebugNuget

  <PropertyGroup Condition=" '$(Configuration)'=='Debug' ">
    <DefineConstants>DEBUG</DefineConstants>
    <!--making this pre-release-->
    <PackageVersion>$(Version)-pre</PackageVersion>
    <!--needed for debugging!-->
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

  <PropertyGroup Condition=" '$(Configuration)'=='DebugNuget' ">
    <DefineConstants>DEBUG</DefineConstants>
    <!--enable package creation-->
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <!--making this pre-release-->
    <PackageVersion>$(Version)-pre</PackageVersion>
    <!--needed for debugging!-->
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <GenerateDocumentationFile>false</GenerateDocumentationFile>
    <!--this makes msbuild creating src folder inside the symbols package-->
    <IncludeSource>True</IncludeSource>
    <IncludeSymbols>True</IncludeSymbols>
  </PropertyGroup>

The Debug configuration enables us to step into the Debug code while we are referencing the project directly during development, while the DebugNuget configuration will also generate a NuGet package including Source and Symbols. This is helpful once you find a bug in the NuGet package and allows us to step into this code also if we reference the NuGet instead of the project. Both configurations will add ‘-pre‘ to the version, making these packages only appear if you tick the ‘Include prerelease‘ CheckBox in the NuGet Package Manager.

Release and ReleaseNuget

  <PropertyGroup Condition=" '$(Configuration)'=='Release' ">
    <DefineConstants>RELEASE</DefineConstants>
    <PackageVersion>$(Version)</PackageVersion>
  </PropertyGroup>

  <PropertyGroup Condition=" '$(Configuration)'=='ReleaseNuget' ">
    <DefineConstants>RELEASE</DefineConstants>
    <PackageVersion>$(Version)</PackageVersion>
    <!--enable package creation-->
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <!--include pdb for analytic services-->
    <DebugType>pdbonly</DebugType>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>

The relase configuration goes well with less settings. We do not generate a separated symbols-package here, as the .pdb-file without the source will do well in most cases.

Adding Build Targets

We are close to finish our implementation already. Of course, we want to make sure we push only the latest packages. To ensure this, we are cleaning all generated NuGet packages before we build the project/solution:

  <!--cleaning older nugets-->
  <Target Name="CleanOldNupkg" BeforeTargets="Build">
    <ItemGroup>
      <FilesToDelete Include="$(ProjectDir)$(BaseOutputPath)$(Configuration)\$(AssemblyName).*.nupkg"></FilesToDelete>
    </ItemGroup>
    <Delete Files="@(FilesToDelete)" />
    <Message Text="Old nupkg in $(ProjectDir)$(BaseOutputPath)$(Configuration) deleted." Importance="High"></Message>
  </Target>

MSBuild provides a lot of options to configure. We are setting the BeforeTargets property of the target to Build, so once we Clean/Build/Rebuild, all old packages will be deleted by the Delete command. Finally, we are printing a message to confirm the deletion.

Pushing the packages

After completing all these steps above, we are ready to distribute our packages. In our case, we are copying the packages to a local folder with the Copy command.

  <!--pushing to local folder (or network path)-->
  <Target Name="PushDebug" AfterTargets="Pack" Condition="'$(Configuration)'=='DebugNuget'">
    <ItemGroup>
      <PackageToCopy Include="$(ProjectDir)$(BaseOutputPath)$(Configuration)\$(AssemblyName).*.symbols.nupkg"></PackageToCopy>
    </ItemGroup>
    <Copy SourceFiles="@(PackageToCopy)" DestinationFolder="C:\TempLocNuget" />
    <Message Text="Copied '@(PackageToCopy)' to local Nuget folder" Importance="High"></Message>
  </Target>

  <Target Name="PushRelease" AfterTargets="Pack" Condition="'$(Configuration)'=='ReleaseNuget'">
    <ItemGroup>
      <PackageToCopy Include="$(ProjectDir)$(BaseOutputPath)$(Configuration)\$(AssemblyName).*.nupkg"></PackageToCopy>
    </ItemGroup>
    <Copy SourceFiles="@(PackageToCopy)" DestinationFolder="C:\TempLocNuget" />
    <Message Text="Copied '@(PackageToCopy)' to local Nuget folder" Importance="High"></Message>
  </Target>

Please note that the local folder could be replaced by a network path. You have to ensure the availability of that path – which adds in some additional work if you choose this route.

If you’re running a full NuGet server (as often happens in Enterprise environments), you can push the packages with this command (instead of the Copy command):

<Exec Command="NuGet push "$(ProjectDir)$(BaseOutputPath)$(Configuration)\$(AssemblyName).*.symbols.nupkg" [YourPublishKey] -Source [YourNugetServerUrl]" />

The result

If we now select the DebugNuget/ReleaseNuget configuration, Visual Studio will create our NuGet package and push it to our Nuget folder/server:

Let’s have a look into the NuGet package as well. Open your file location defined above and search your package:

As you can see, the Copy command executed successfully. To inspect NuGet packages, you need the NuGet Package Explorer app. Once installed, just double click the package to view its contents. Your result should be similar to this for the DebugNuGet package:

As you can see, we have both the .pdb files as well as the source in our package as intended.

Conclusion

Even as an Indie developer, you can take advantage of the DevOps options provided with Visual Studio and MSBuild. The MSBuild.Sdk.Extras package enables us to maintain a multi-targeting package for our Xamarin(.Forms) code. The whole process needs some setup, but once you have performed the steps above, extending your libraries is just fast forward.

I planned to write this post for quite some time, and I am happy with doing it as my contribution to the #XamarinMonth (initiated by Luis Matos). As always, I hope this post is helpful for some of you. Feel free to clone and play with the full sample I uploaded on Github.

Until the next post, happy coding, everyone!

Helpful links:

Title image credit

P.S. Feel free to download the official app for my blog (that uses a lot of what I am blogging about):
iOS | Android | Windows 10

Posted by msicc in Azure, Dev Stories, iOS, UWP, Xamarin, 3 comments
Integrate crypto payments into your .Net applications with AtomicPay

Integrate crypto payments into your .Net applications with AtomicPay

If you have been following along, you may have noticed that I am discovering the cryptocurrency space lately. Today I want to introduce you to AtomicPay, a crypto payment processor that uses a different approach than traditional processors.

Why AtomicPay?

I have been thinking quite some time about how one can implement crypto payments into apps, be it desktop or mobile apps. Ever since then, it was clear for me that I need a solution where the payment happens between me and the customer directly, but all the infrastructure to handle invoicing etc. has to be handled from the outside.

Traditional payment processors often provide their service with a custodial wallet – you do not have control of the keys, so it is not really your wallet, just the grant to use it. Processing incoming transactions to this custodial wallet are routed through another wallet of the service, where those processors take their fees and process the reduced payment to your custodial wallet.

Security and Privacy

When it comes to crypto payments, there is always one problem: the balance between the ease of using and security/privacy. If you are looking at some other non-custodial services, they are providing payment processing by just using a single wallet address. Even if this is the easiest way to use crypto payments, it has some fundamental issues:

  • makes it way too easy to monitor transactions of a business/merchant entity
  • easy target for man-in-the-middle attacks
  • accountability issues (imagine 10 people paying the same amount, but for different products at nearly the same time)

Do you really want to put you and your customer/user at this risk? Surely not!

AtomicPay’s different approach

AtomicPay follows a different route. It provides an invoicing infrastructure that is easy to use, but payments are directly between merchant and customer.

It relies on the well established Electrum wallets. Never used any Electrum wallet before? No worries, AtomicPay helps you to initialize the wallet with step-by-step tutorials.

Electrum wallets are (optionally) SegWit-enabled, HD (hierarchical determistic) wallets. This means that for every incoming transcation, a new address is generated from your keys. Even though you could do multiple times, every address should be used only once. This makes attacks from the outside significantly harder and protects both you and your customer/user.

AtomicPay itself only has reading access – it can watch transactions, but never initialize any transfer out of the wallet of your funds. Atomicpay is able to calculate new valid receiver addresses for your Electrum wallet because of the BIP 0032 protocol by using your public key, which is the only thing you need to insert into their website.

AtomicPay features

AtomicPay provides quite a bunch of features:

  • on-the-fly PayUrl generation (QuickPay)
  • monitoring of incoming payments
  • notifications via Mail and Webhook
  • free-to-use REST API
  • very low fees
  • and more…

Introducing AtomicPay.Net SDK

As AtomicPay convinced me to be a valuable solution for crypto payments, I started to create a new library for their API. The SDK makes it very simple to call all endpoints and to integrate it into your .NET applications. The library is available on Github and as NuGet package. You’ll find informations on how to use the library on Github as well. My repo will also be forked into AtomicPay’s Github account soon and gain a bit more visibility this way.

What’s next?

The library is only the first step and lays the groundwork for more things to come, namely:

  • Webhook code sample with Azure Function and Notificationhub
  • Xamarin component for AtomicPay
  • Administration app for merchants (iOS and Android)

If you have ideas or questions on the library, feel free to ping me on the well known social accounts or leave a comment under this post. As always, I hope the library will be helpful.

Until the next post, happy coding, everyone!

Disclaimer: I am contributing to this project with code written by me under the MIT License. Future contributions may contain their own (and different) disclaimer. I am not getting paid for my contributions to the project.

Please note that none of my crypto related posts is an investment or financial advice. As crypto currencies are volatile and risky,  you should only invest as much as you can afford to lose. Always do your own research!

Posted by msicc in Crypto&Blockchain, Dev Stories, 0 comments
WordPressReader (Standard) version 1.2.0 focuses on improving performance

WordPressReader (Standard) version 1.2.0 focuses on improving performance

The update contains several improvements to the HttpClientimplementation, which should improve performance of the library a lot:

  • all handlers now use one static HttpClientinstance. HttpClientis built to use it that way, and there is also no problem with multiple request handled by that instance. So everyone should use it in that way
  • the library is now actively enforcing gzip/deflate compression to make responses faster, especially when requesting bigger lists of items (if you want do deactivate it on the managed implementation, pass in falsewith the new useCompressionparameter with your call to the SetupClientmethod
  • deserialization by default now happens directly from the HttpResponsestream instead of first converting it to a string
  • added an API to pass in your own HttpClientinstance instead of the managed one (you could even use one static instance for your whole app this way to improve performance even further). To do so, just use the newly added method SetCustomClient(HttpClient client)on your handler instances.

I made this changes working without breaking existing implementations. Just by updating the library, you will get a better performance.

I also updated the source code on GitHub. If you just want to update the library, the update is already available on NuGet.

Happy coding, everyone!

P.S.
If you want to see the library in a live app, you can download my official blog reader app (which is written around it as a Xamarin.Formsapp) here:

iOS  Android  Windows 10

Posted by msicc in Dev Stories, 1 comment
WordPressReader (Standard) library is now available on Nuget

WordPressReader (Standard) library is now available on Nuget

I am happy to announce my new WordPressReader (Standard) library that is available on NuGet now. It is written in .netStandard 1.4 which enables you to use it in a lot of of places. As the name suggests, it focuses on reading tasks against the WordPress API.

Features:

  • get, search and filter posts
  • get pages
  • get and filter categories
  • get, search and filter tags
  • get comments
  • post anonymous comments (needs additional work on the WordPress site)
  • get basic user info

The library uses a generic WordPressEntity model implementation, which makes it easy to implement and extend. You can always get the raw json-value as well. The additional Error property on every model makes it easy to handle API errors properly. You can read the full documentation in the GitHub Wiki.

If you have problems with the library or want to contribute, you can do so on the GitHub repo.

Happy coding, everyone!

P.S.
If you want to see the library in a live app, you can download my official blog reader app (which is written around it) here:

iOS  Android  Windows 10

 

Posted by msicc in Dev Stories, 2 comments

[Updated] How to create a multi architecture NuGet Package from a UWP class library

Like I already announced in my last blog post about UWP AppServices, I am going to show you how to create a NuGet package for UWP class libraries. I am going to go through the whole process, and provide you the steps I found as easiest (it may be the case that there are other ways for the single steps, too). I am continuing with my AppServices sample to show you all the steps I did.

Preparations

The first step is to download the latest NuGet.exe. This command line application will do all the work that is needed to create the package. Once downloaded, let’s do some modifications to our project.

It is good practice to put all the NuGet stuff into a folder in your project. That’s what we’re doing now, adding a folder named NuGet and put the NuGet.exe file in it (create the folder and copy and paste it in file explorer). The next step we would do now is to open the Package Manager Console in Visual Studio and call the nuget.exe with the parameter ‘spec’ to create a .nuspec file. The.xml formatted .nuspec file describes the structure of the NuGet package.

Because we need a multi architecture package for our Universal class library, I prefer another approach. I created a sample .nuspec file that already describes part of the structure that we need.  After pasting the file in, change the file name to match “[projectname].nuspec”. To add the file to your project in Visual Studio, click on the ‘ Show All Files’ button on top of the Solution Explorer Window. Now you will see the previously added NuGet folder and the .nuspec file. Right click on the renamed .nuspec file and select  ‘Include in Project’:

image

Inside the .nuspec file

Let’s have a look into the .nuspec file. The first part is the ‘metadata’ part, which describes the file’s properties:

    <metadata>
        <id>$title$</id>
        <version>$version$</version>
        <title>Simple Leet AppService Handler</title>
        <authors>$author$</authors>
        <owners>$owner$</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>$description$</description>
        <copyright>Copyright ©  2016</copyright>
      
        <dependencies>
        </dependencies>
    </metadata>

Just replace the the $-enclosed variables with your data. The more interesting part in this case is the dependencies part. With the Universal app platform, Microsoft introduced the .NETCore package that provides all the APIs. It is very hard to maintain the dependencies manually. Luckily, there is already a Nuget package that helps us to automate this process: NuSpec Dependency Generator.

Just add the package to your project and compile it. That’s it, you have all the dependencies in your .nuspec file:

    <dependencies>
      <group targetFramework="uap10.0">
        <dependency id="System.Diagnostics.Debug" version="4.0.10" />
        <dependency id="System.Runtime" version="4.0.20" />
        <dependency id="System.Runtime.WindowsRuntime" version="4.0.10" />
        <dependency id="System.Threading.Tasks" version="4.0.10" />
      </group>
    </dependencies>

Now that we have the dependencies in place, we’re ready for the next step: creating the package file structure. As we want a multi architecture package, we need to compile the project for every cpu architecture. This is done pretty simple, just select Release mode and build the project for all architectures:

Screenshot (97)

To check if we have all files in place, just open the corresponding architectures’ folder in the bin folder of your project:

Screenshot (98)

The next part is to add these folders to the .nuspec file within the ‘files’ tag:

  <files>
    <file src="..\bin\ARM\Release\SampleAppServiceConnector.dll" target="runtimes\win10-arm\lib\uap10.0" />
    <file src="..\bin\ARM\Release\SampleAppServiceConnector.pdb" target="runtimes\win10-arm\lib\uap10.0" />
    <file src="..\bin\x64\Release\SampleAppServiceConnector.dll" target="runtimes\win10-x64\lib\uap10.0" />
    <file src="..\bin\x64\Release\SampleAppServiceConnector.pdb" target="runtimes\win10-x64\lib\uap10.0" />
    <file src="..\bin\x86\Release\SampleAppServiceConnector.dll" target="runtimes\win10-x86\lib\uap10.0" />
    <file src="..\bin\x86\Release\SampleAppServiceConnector.pdb" target="runtimes\win10-x86\lib\uap10.0" />
  </files>

Noticed that we use the ‘runtimes’ folder with the corresponding architecture structure folders? This is how we need to set it up for multi architectural packages. Including the .pdb files is always a good practice, even with the missing symbolication in UWP applications (at least for now. I was told from inside Microsoft that they are working on this, but it seems to be a very complicated process for .NET native compiled applications).

Very important: the entry reference

This alone does not work, though. We need a reference that we can use as entry point for our package. To do this, we need to add an additional folder entry to our .nuspec file:

    <file src="..\bin\Release\SampleAppServiceConnector.dll" target="ref\uap10.0" />
    <file src="..\bin\Release\SampleAppServiceConnector.pri" target="ref\uap10.0" />

[Update:] Now that we have added this folder structure to the .nuspec file, the only thing we need to do is add an AnyCPU compiled .dll. Regarding some feedback I received on Twitter, it should work if you compile the library as AnyCPU like a lot of devs are used to. I you do not have success with that like me, you can also convert the x86 .dll into an AnyCPU .dll by removing the 32Bit-flag.  Here is how to do it:

  1. Copy the x86-.dll file  into the Release folder under the bin folder of your project
  2. Copy the x86-.dll and .pri file into the Release folder
  3. open the Visual Studio Developer Command Prompt (type ‘dev’ into the start menu, it will appear there)
  4. type:  corflags.exe /32bitreq- [path to Release folder]\[dll-Name].dll
  5. the result should look like this:Screenshot (101)

If you have additional files like xaml files, you would need to add a new folder in the uap10.0 folder (with the same name that your project has). I’ll update this post and the sample once I have a matching sample at hand.

Creating and testing the package!

Now we are finally able to pack the NuGet package. As we have the Developer Command Prompt already open, lets change the running directory to match the NuGet folder in our project. All we then need to do is to run the pack command of the nuget.exe that we already placed in there:

image

And that’s it. We have our NuGet Package in place. Now let’s test our package, before we are going to upload it to nuget.org. All you need to do is to have a folder for your NuGet packages on your machine. I made a folder called ‘TestNuget’ on mine, and copied the package into it (which is the same as the Nuget push command we’ll see later).

To add this folder as package source, open the ‘Options’ menu in Visual Studio and select ‘Package Sources’ in the NuGet Package Manager entry. Hit the add symbol on top and add your folder:

Screenshot (104)

Now if you open the Package Manager and select your local folder as source, you will be able to install and test your package:

image

Publishing the package to nuget.org (or your NuGet server)

The final step is to publish the newly generated package to nuget.org or your own NuGet server. As we still have the Developer CMD opened, we simply use the following command:

nuget push [path to your package.dll] [nuget.org API Key]

Another alternative would be to use the nuget.org website to upload the package: https://www.nuget.org/packages/upload (the page is self explanatory).

That’s it, your NuGet package is available for all you consider to use it. I also updated the sample of my last blog post on GitHub to include these changes, if you want to play around.

Some of you may go a different route for some steps. I have found this a good way that is also kind of memorable (for me). I would love to hear feedback on this and to discuss this, so feel free to leave me a comment.

Like always, I hope this post is helpful for some of you. Happy coding, everyone!

Posted by msicc in Dev Stories, UWP, windev, 4 comments