Nuget package

[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, 3 comments

How to add and consume an AppService to your UWP app (complete walkthrough)

One of the very cool and helpful new features Microsoft added for UWP apps are AppServices. AppServices allow your application to provide functionality to other applications without even being launched. This post shows how to add and consume an AppService.

Creating the AppService

An AppService is a background task that is hosted by your application. To add an AppService to your existing application, right click on the solution name in the Solution Explorer and select ‘add new  project’. Under category Windows\Universal, select ‘Windows Runtime Component’, give it a name and click on ‘OK’:

image

This adds a new project to your solution. Rename or Replace Class1.cs to something that matches your need (in my sample, I just use ‘Handler’). The next step is to implement the IBackgroundTask interface:

image

This will add the ‘Run(IBackgroundTaskInstance taskInstance)’ method to the class. Before we continue with to integrate our AppService further into the system, we need to declare two members in the Handler class:

        private BackgroundTaskDeferral _backgroundTaskDeferral;
        private AppServiceConnection _appServiceConnection;

Now that we have those two in place, let’s have a look inside the Run method:

       public void Run(IBackgroundTaskInstance taskInstance)
        {
            //get the task instance deferral
            this._backgroundTaskDeferral = taskInstance.GetDeferral();

            //hooking up to the Canceled event to close app connection
            taskInstance.Canceled += OnTaskCanceled;

            //getting the AppServiceTriggerDetails and hooking up to the RequestReceived event
            var details = (AppServiceTriggerDetails)taskInstance.TriggerDetails;
            _appServiceConnection = details.AppServiceConnection;
            _appServiceConnection.RequestReceived += OnRequestReceived;
        }

The first step is to get a background task deferral. This allows the service to run asynchronous code against the background Task without crashing. The next step is to handle the background task’s Canceled event. Even if the Task get’s cancelled, we must complete the process and tell the OS that we have finished. If we won’t do this, the AppService will stop working on the first cancel operation. To do so, add this code to your Canceled event handling method:

            this._backgroundTaskDeferral?.Complete();

Last but not least, we need to handle the request that the AppService received. To do so, we need to get the AppServiceTriggerDetails from our BackgroundTask. This allows us to get  a reference to the AppServiceConnection, which provides the event ‘RequestReceived’ that we want to handle.

Within our RequestReceived event handling method, the effective work is done. As this is also an asynchronous action, we first need to get again a reference to the event’s Deferral:

var msgDeferral = args.GetDeferral();

The next step is to get the data from the event’s AppServiceRequestReceivedEventArgs:

            var input = args.Request.Message;

This gives us a ValueSet (which works like a Dictionary), which we need to parse to get the input data we need:

var response = (string) input["question"];

The ValueSet entries you are setting up here are the parameters your consumer has to provide. In my sample, I have only a single parameter called ‘question’, but it works also well with more parameters. After we pulled the parameters out of the ValueSet, we can do the work our AppService is supposed to do.

It is a good practice to separate the function you want to provide in the AppService in a separate project. You need to write the code only once, but can use it in your main application as well as in the AppService. In my Sample, this is done in the AppServiceResponder project. It may look like an overkill in this case, but if you have more complex logic than the sample it will absolutely make sense.

I am wrapping the work into a try/finally block as we need to complete the async operation in any case to keep our AppService running. This way, even if the work is not completed successfully, at least we come out clean of the AppService Task. Within the try part of the try/finally block, we are doing the work that the service is supposed to do. The result needs to be passed as a ValueSet again. To effectively send the result to the requesting app, we use this line of code:

await args.Request.SendResponseAsync(result);

Here is the full method for reference:

        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            //async operation needs a deferral
            var msgDeferral = args.GetDeferral();


            //picking up the data ValueSet
            var input = args.Request.Message;
            var result = new ValueSet();

            //parsing the ValueSet
            var response = (string) input["question"];

            try
            {
                //as long as the app service connection is established we are using the same instance even if data changes.
                //to avoid crashes, clear the result before getting the new one
                result.Clear();

                if (!string.IsNullOrEmpty(response))
                {
                    var responderResponse = AppServiceResponder.Responder.Instance.GetResponse(response);

                    result.Add("Status", "OK");
                    result.Add("response", responderResponse);
                }

                await args.Request.SendResponseAsync(result);
            }
            //using finally because we need to tell the OS we have finished, no matter of the result
            finally
            {
                msgDeferral?.Complete();
            }
        }

Declaring the App Service in the host app

The final step we need to apply is to declare the AppService in our Package.appxmanifest. Declaring the AppService is pretty simple. Just select ‘App Service’ in the dropdown and hit ‘Add’. Give it a name (Microsoft recommends ‘reverse domain name style ‘,  so I used it. The last step is to declare the Entry point, which is AppServiceNamespace.ClassName (replace with yours).

The result should look like this:

image

Now build the solution. If all is set up correct, you have made an application implementing an AppService.

Creating the AppService Connector

Like I recommend to extract functionality that runs inside the AppService, I do so for the code that connects the app into a separate project. This allows you to reuse the project in multiple apps. An additional advantage is that you can create a Nuget package for this separate project to provide this functionality to other developers (I will write a separate post about this to keep this one focused on the AppService).

After adding a new project to the Solution, rename/replace also here Class1. I named my handler class just Connector. To make it a no brainer to use the connector, I implemented the class as singleton:

        private static Connector _instance;
        public static Connector Instance => _instance ?? (_instance = new Connector());

After that, I added an asynchronous Task that returns the AppService’s response. Let’s have a look inside the task. Inside the using statement for the AppServiceconnection, the first thing we need to do is to call the AppService with these three lines of code:

                //declaring the service and the package family name
                SampleAppServiceConnection.AppServiceName = "com.msiccdev.sampleappservice";

                //this one can be found in the Package.appxmanifest file
                SampleAppServiceConnection.PackageFamilyName = "acc75b1a-8b90-4f18-a2c4-08b0d700f1c6_62er76fr5b6k0";

                //trying to connect to he AppService
                AppServiceConnectionStatus status = await SampleAppServiceConnection.OpenAsync();

We’ll get a AppServiceConnectionStatus back, which helps us to deside how to go on in the task. If we do not have success in getting a connection to the AppService, I am returning an error description. For this, I created a simple helper method:

        private string GetStatusDetail(AppServiceConnectionStatus status)
        {
            var result = "";
            switch (status)
            {
                case AppServiceConnectionStatus.Success:
                    result = "connected";
                    break;
                case AppServiceConnectionStatus.AppNotInstalled:
                    result = "AppServiceSample seems to be not installed";
                    break;
                case AppServiceConnectionStatus.AppUnavailable:
                    result =
                        "App is currently not available (could be running an update or the drive it was installed to is not available)";
                    break;
                case AppServiceConnectionStatus.AppServiceUnavailable:
                    result = "App is installed, but the Service does not respond";
                    break;
                case AppServiceConnectionStatus.Unknown:
                    result = "Unknown error with the AppService";
                    break;
            }

            return result;
        }

For the case we are successful with our connection attempt , I am sending the needed ValueSet with these lines:

                    var input = new ValueSet() {{"question", question}};
                    AppServiceResponse response = await SampleAppServiceConnection.SendMessageAsync(input);

I am using a simple ValueSet with just one value here, but I have already done it with a more complex structure and this works as well. I haven’t reached any limits by now, but I think that they are the same as for all Background Tasks (don’t throw stones at me if it is different). The only thing I then need to do is to handle the response according to its status with this switch statement:

                    switch (response.Status)
                    {
                        case AppServiceResponseStatus.Success:
                            result = (string) response.Message["response"];
                            break;
                        case AppServiceResponseStatus.Failure:
                            result = "app service called failed, most likely due to wrong parameters sent to it";
                            break;
                        case AppServiceResponseStatus.ResourceLimitsExceeded:
                            result = "app service exceeded the resources allocated to it and had to be terminated";
                            break;
                        case AppServiceResponseStatus.Unknown:
                            result = "unknown error while sending the request";
                            break;
                    }

As we already know by know, we receive a ValueSet as response message. In my sample, I am returning only the response string. That’s it, we are already able to run use the AppService via the Connector. For demo purposes, I added also a simple AppService consumer app. Once the user puts in a question and hits the answer button, the result from the AppService gets displayed. All we need is just one line of code:

            AnswerTextBlock.Text = await SampleAppServiceConnector.Connector.Instance.GetResponse(QuestionTextBox.Text);

Pretty easy to use, right? Here is a screen shot from the consumer app:

image

That’s all we need for our AppService. Bonus of the project structure I used: You can provide a Nuget Package for other devs to consume your AppService. How? I will write about this in my next blog post.

Even if this is not a MVVM structured app, it absolutely works in there, too. If you want to have a look on a live in the Store app that uses MVVM and an AppService, click here. For using the AppService within your app, just download this Nuget Package into your app. Otherwise, I created a complete working sample and pushed it on my Github account right here. Feel free to play around with it to explore AppServices a bit more. As always, I hope this post is helpful for some of you.

Happy coding, everyone!

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