Sunday, December 22, 2019

[ADVENT 2019] F# Advent 2019: Revisiting Windows Forms and WPF in F# on .NET Core 3.1

Hi my blog readers!

Now it's time for F# Advent 2019! This annual advent showcases F# bloggers and their articles, in December, thanks to Sergey Tihon, a fellow MS MVP. This year, the complete list of F# Advent 2019 is available at: https://sergeytihon.com/2019/11/05/f-advent-calendar-in-english-2019/

I had submitted schedule for 22nd December by replying to his tweet: https://twitter.com/sergey_tihon/status/1191558104506343425

So let me bring you F# on top of .NET Core 3.1, with code that runs Windows Forms (a.k.a. WinForms) and WPF.

Is this possible? The simple answer is YES. Although there's no new template to create WinForms and WPF in "dotnet new".

The list of available templates are shown when we execute "dotnet new -h":


Yes, it's only available for C#:


So how to have these WPF and WinForms using F#?

It is a bit tricky, but thanks to .NET Core 3.0's new ways of referencing "contextual" technology references, we can leverage WPF and WinForms.

Before .NET Core 3.0

Before .NET Core 3.0, we have to use metapackages combined with specific SDK header in the csproj/fsproj/vbproj, and this metapackage combination with SDK are somehow hard to understand.

It is not so obvious that the SDK and the metapackage are not well integrated, because you still have to specify some of the .NET Core libraries to use as nuget package references. This is quite common in ASP.NET Core templates before 3.0.

Let's use the .NET Core 2.2 latest SDK, 2.2.207 to illustrate this.
To ensure that I'm using at least SDK 2.2.207, I use global.json on the solution/project folder to enforce .NET Core to use the SDK version I want, not choosing the latest release of SDK available.

I had created a global.json file with SDK version, by using the "dotnet new global.json --sdk-version 2.2.207" on command prompt.

This is the content of the global.json:

{
  "sdk": {
    "version": "2.2.207"
  }
}

We can test this by running "dotnet --version", and it will give you the version of the SDK as set in the global.json file.

To create an ASP.NET Core MVC web app in .NET Core 2.2, we use this template when creating using "dotnet new". Now let's create new F# ASP.NET Core MVC and named is as FSharpMVC:

dotnet new mvc -n FSharpMVC -lang F#

This is the content  of the FSharpMVC.fsproj file:



And there is a nuget package reference to "Microsoft.AspNetCore.App", and this is a sample of a metapackage.

Also note the use of SDK in the <Project> header:
Sdk="Microsoft.NET.Sdk.Web"

This means that this is generated using ASP.NET Core template. Unfortunately, not all the ASP..NET Core libraries are included in that metapackage. You still have to reference them as nuget package references, and at many times this may get messy.

For example: references to Microsoft.Extensions.Configuration.* are all have to be referenced as nuget packages explicitly, Also before .NET Core 3.0, there's no support for WinForms and WPF.

After .NET Core 3.0

Now we have WinForms and WPF support as port from .NET Framework to .NET Core in .NET Core since 3.0.

In this article, I focus on .NET Core 3.1 because this is the LTS release. The LTS means that this release of 3.1 has long time support compared to 3.0.

On the SDK,, I use .NET Core 3.1.100 SDK at the time of this writing.

To create a new F# project to have WinForms and WPF, I could just use console as template. Because currently no default template support for F# for WinForms and WPF.

We should use global.json to enforce the SDK to be 3.1.100, then create the project, like this:

dotnet new console -n FSWinfowsDesktop -lang F#

By default, console project of F# and C# always have base SDK in the <Project> header.
Now let's look at the content of FSWindowsDesktop:



We can leverage the "FrameworkReference" to have references to .NET Core SDK libraries in a separated contexts as previously described as metapackage before 3.0. This is an often overlooked features, although it is very useful!

The Framework reference in .NET Core 3.0/3.1 describes what libraries we want to use besides the base .NET Core libraries. Using VS 2019 16.3.x or later, the FrameworkReferences is shown nicely as "Frameworks":


The Microsoft.NETCore.App is always referenced by default, because this FrameworkReference is the base .NET Core library.

The available valid FrameworkReferences values are available under the Dotnet installation folder under "Shared" of "Program Files" for 64-bit, or "Program Files (x86)" for 32-bit.



Now let's add the Microsoft.WindowsDesktop.App as FrameworkReference, and also explicitly tell the project to use WinForms using <UseWindowsForms> set to true.

We now have this:


Then we can now leverage the references inside our F# code, using the open namespace and we are also guaranteed to have the namespaces available in the intellisense!


To use WPF, we can use <UseWPF> and set to true.
Also we can have both WPF and WinForms by having both <UseWindowsForms> and <UseWPF> both set to true, as long as we have FrameworkReference to Microsoft.WindowsDesktop.App.

To see this sample as a complete sample with the global.json file, I have made the source code available on my GitHub:
https://github.com/eriawan/netcore-fsharp-sample

And last but not least, Merry Christmas and have a happy F# Advent 2019!

😀

Monday, December 16, 2019

Speaking at Global AI Bootcamp 2019

Hi my blog readers!

This December is surely a surprising month, because December is usually the month that no community event gatherings are held in Jakarta, but there is one!

This time I had speaking engagements at Global AI Bootcamp 2019 meetup and workshop, organized by Buitenzorg Makers Club (BMC) and Dicoding. What a busy community, BMC! Some of you have known Fadhil, BMC lead. And under his lead, BMC has active records of having community meetups for more than 4 times/year!

This is the event link: https://www.dicoding.com/events/2782



NOTE:

  1. The Global AI Bootcamp is an annual global meetup/event, initiated by Microsoft with local event supports. that focused on AI on Azure.
  2. The global event in 2019 is in December, although it is usually on November.

The event was held on DiLo Kemenpora, a community place and also coworking space for meetup,

We have also other speakers: Fadhil himself, Endang Suwarna, Amir Umara.

The event is not just an ordinary seminar/presentation, but it also has workshop as well.

The audiences are not many (around 50) but the enthusiasm is so high! At my speaking time, I got asked a lot of heavy questions about AI.

Here are the scenes/pictures of the audiences:




The audiences are so active!

Here we have Fadhil and his crew delivered opening in a fun way:


Then I continued to present ML .NET:


and Visual Studio 2019 is in action:


On my session, I presented ML.NET with step by step tutorial from Microsoft Docs and from this official landing page of ML.NET: https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet

It is always so easy to learn and follow, because the code samples are also there and it is available on GitHub: https://github.com/dotnet/machinelearning-samples

I mainly focused on ML.NET for sentiment analysis and forecasting, because it is quite simple and it's also easy to train the AI model data, compared to other samples.

Then Fadhil presented his AI+IOT demo:


There were other speakers in session as well but I had to leave soon because I had other things to do after I finished my session and providing help for Fadhil and his session.

But of course we always had photo session 😉


It's a wrap, and I have to admit it was quite intense when answering the audiences questions, but again I'm always happy to contribute back to communities!

Thursday, November 21, 2019

Speaking at Global AI/MR Bootcamp 2019 Jakarta

Hi my blog readers!

Oh boy, 2019 is definitely a busy year!

I'm grateful and honored at the same time to have speaking engagements at Global AI/MR Bootcamp 2019 Jakarta meetup event on 16th November, 2019.
The event was organized by collaborations of Mixed Reality Community Indonesia and MUGI, with speaker from Buitenzorg! Yes, this is a full collaborative community event, mostly focusing on AI/MR (Mixed Reality). Thanks to Microsoft Indonesia for generously lend us the venue!


The speakers were me (MUGI), Adityo (MR Indonesia), Fadhil (from Buitenzorg). There was Riza that supposed to come and speak, but he was sick at the time of the event.




Here Adityo was giving the opening statement:


And accompanied with a cool AI/MR video from Microsoft:


Then he showed and presented cool HoloLens with his HoloLens app!



I presented AI in Visual Studio, especially  the trained AI of Intellicode in VS 2019:




And I also presented the ML.NET.

Last but not least, Fadil presented the AI on his IOT crafted devices:




The audiences were so enthusiasts and some of them grilled us with hard questions! GREAT!

It was quite a blast!

See you on the next MUGI Jadetabek event, guys! :)


Monday, October 28, 2019

Speaking at local Purwokerto's .NET Conf 2019 meetup!

Hi my blog readers!

If you have followed my blog trails, you'll see that this year (2019) since January I am mostly invited as speakers in various Indonesian meetups, especially topics on .NET, Azure, and Azure DevOps!

On 26th October, I was invited to speak at MUGI Purwokerto's event of .NET Conf 2019, at UNSOED Purwokerto. Thanks for the invitation, my MVP colleague Agus Suparno!

I'm so excited, because my other MVP colleague, Agus Kurniawan is also invited as speaker, not just Agus Suparno and me!



In this event I spoke about "Best practice of  .NET Core 3.0 CI/CDs using Azure DevOps", Agus Kurniawan presented .NET support for Apache Spark, and Agus Suparno talks about .NET ML (Machine Learning).

The audiences were enthusiastic, and there were some questions to me, especially when they want to start to learn .NET as platforms, especially there was an exchange student, he was Adnan Derbani. Thanks for adding me on LinkedIn!

Here are Agus K, Agus S and me presenting, starting from me:





And Agus Suparno:


Then Agus Kurniawan:



We also have learned some Big Data in Management perspective from Dr.Ade Irma Anggraeni, Senior Lecturer at UNSOED. Cool!




And a surprise bonus, a DevOps for practical for companies, presented by Darmawan Suandi:



Wow, it was a blast!

Can't wait to start more collaboration with other communities outside Jakarta! 😊❤

Saturday, June 22, 2019

Speaking at MUGI Jadetabek with Buitenzorg to present "BUILD 2019 viewing (NOBAR)"

Hi my blog readers! Do you enjoy watching Microsoft BUILD 2019?

I enjoyed so much, and I hope you too!

This month, MUGI Jadetabek and Buitenzorg Maker's Club (IOT community) in Bogor have worked together to bring BUILD 2019 Viewing (a.k.a. Best of BUILD 2019) meetup on 19th June, 2019.

The BUILD 2019 Viewing meetup is also held quite simultaneously on many countries and cities, and in Indonesia the event is held in Jakarta. This time MUGI collaborate with Buitenzorg Maker, an IOT community that lead by Fadhil, who is also a Microsoft MVP. The venue is on Microsoft Indonesia's auditorium, and thanks to Yos Vincenzo for helping us to register and book a room!

This is the event link on MUGI: https://www.meetup.com/MIcrosoft-UserGroup-Indonesia-charter-Jadetabek/events/262411622/


In this meetup, we got more than one speakers!

The first one is me, the others are Fadhil and Gilang (from Blocksphere Indonesia). Gilang is an expert on Blockchain, and other cool speakers as well, and I could not mentioned all of them because I have to leave early.

Since MUGI and I are not the main organizer, I leave the credit to Buitenzorg and Fadhil as the main organizer, although I have displayed this event as part of MUGI Jadetabek event. Thanks for having me! 🙏😊

I presented a topic on video of "Container From Zero to DevOps" (including Kubernetes) on Azure (presented by Jessica Deen), and also giving a special time have Q&A later.



Here's Fadhil presented ONNX for AI/ML:


Here's Gilang presenting Blockchain on Azure:



And to my surprise, the attendances were full enthusiastic!


Yup, we have more than 80 folks coming! 😊

The Buitenzorg Makers has more photos, so please visit their Facebook page!

Monday, March 25, 2019

Speaking at Louisville .NET meetup,remotely speak and presenting Best practice of .NET Core CI/CD on Azure DevOps

Hi my blog audiences! Oh boy, another speaking time!

In February, I had speaking arrangements with Louisville .NET meetup, and Chad Green, the meetup's owner. Since December 2018, he had announced opportunity to speak for his meetup.

This is the Louisville .NET meetup page on Meetup.com:
https://www.meetup.com/Louisville-DotNet/

I'm honored, and at the same time feel so privileged to speak for his meetup, particularly knowing that English is not my first language. The topic I presented was about "Best practices of .NET Core 2.1 CI/CD using Azure DevOps".

This is the landing page of the event: https://www.meetup.com/Louisville-DotNet/events/258017408/




In this context, I focused on Azure DevOps Service. Yes, Azure DevOps Service is a rebrand from VSTS (also known before as Visual Studio Online).

NOTE: For those who wonders, the on-premise TFS will be named as Azure DevOps Server, and it will be released under the name of Azure DevOps Server 2019.

Thanks to Chad, he agreed to use Skype to speak and present for them (by sharing my desktop screen).

Here is the audience at that time (taken from my desktop screen: (on Skype)



The presentation


I had prepared the material and the talk before, including a github repo (link below) to specifically contain the presentation, the sample and demo.


The best practices for .NET Core 2.1 CI/CD are mostly concluded into these 3 main ideas (and also topics):

  1. Build and test locally first, without Visual Studio 2017 at all. It is recommended to use command prompt. Then use the knowledge and experience later to create CI on Azure DevOps
  2. Prepare and Implement Azure DevOps CI/CD.
  3. DOs and DON'Ts of Azure DevOps CI/CD 




The first topic is important, because Visual Studio 2017 always hides all of the mechanics that happened when you compile a solution. It is using MSBUILD, but the actual running sequence is always this:


  1. Restore and resolve all nuget packages using the .NET TFM information. For example: .NET Core 2.1 TFM is "netcoreapp2.1". The restore and resolve done at each project. The way nuget execute is closely related to the MSBUILD version used AND the VS 2017 used.
  2. Compile the projects in the solution, and check with resolved nuget packages
  3. If the RID specified, then "dotnet build" will tell MSBUILD to generate the necessary RID as well. Often, RID is liked with the OS used as target runtime OS.

Point #1 is important, because Nuget-MSBUILD-.NETCoreSDK-VS2017 usually has linked "train release" toolchain that we can't ignore.

For example:



Also getting used to know TFM is important, because .NET Core SDK project is editable from Visual Studio, and many tutorials from Microsoft shown these.

For more information on list of .NET Core TFM, please visit this official documentation: https://docs.microsoft.com/en-us/dotnet/standard/frameworks

By default, "dotnet build"  always use the latest SDK to compile. This will cause problem if you have many versions of .NET Core 2.1 SDK on your machine! The reason is quite trivial: the compilation and the assembly resolution will be different with your targeted TFM.

The way to minimize this is using "global.json" file that contains the .NET Core SDK you want to use, and put this on the solution folder.

For example:

{
  "sdk": {
    "version": "2.1.503"
  }
}

For more information on global.json syntax and usage, visit this official documentation: https://docs.microsoft.com/en-us/dotnet/core/tools/global-json

For more on my presentation, visit my repo of dotnetcore CI/CD sample: https://github.com/eriawan/dotnetcore-cicd-samples

Get the code


In my own Azure DevOps account, I have setup a sample CI to be shown as public, so the audience can follow my demo and presentation later.

The Azure Pipelines builds log for this meetup is available at: https://dev.azure.com/rxcommunica/rxpubliccrepo/_build?definitionId=18

So? Fork my repo and start doing DevOps now! :)