Sunday 21 October 2018

Flutter Mobile UI Framework

Flutter is a new mobile UI framework from Google, that allows you to create native applications on iOS and Android. At the time of writing this blog post, it's still in beta but apparently will hit 1.0 soon!

Now, I gotta say, when I first learned about Flutter, and what it was all about, I was very intrigued!

You see, Flutter is the equivalent of a game-engine but for everyday apps!! I'll let that sink in. It's got an OnDraw function just like a game engine's loop would call (they call it the build function). Under the covers it uses the C++ library Skia to draw pixels directly on the screen. And because its C++ underneath, that means Flutter is cross-platform. Needless to say, this warrants a closer look from anyone who is writing mobile applications.

I'll say it up top! - Flutter looks very cool.

Stepping back a bit, I've always thought that as C++ is the lingua franca of languages, which all systems support, could it be possible for someone to write a cross platform mobile UI framework using SDL or SFML. It was a fleeting thought of course because that's no simple undertaking. Yes, I know we already have the C++ Qt library and QML but the masses aren't exactly flocking to use it.

Then there are game-engines like Unity that can run on all platforms. Again, I have always wondered if it would be be feasible/possible to use it to write a line-of-business app? I mean, it uses C# (which is a win) and the app would run everywhere Unity runs! That's a lot of places. But again, you would have to write the GUI widgets/controls yourself. The amount of work involved would be massive!

Enter Flutter.

Turns out Google was thinking the same thing, because that's what Flutter is all about. It's written in both C++ & Dart. C++ is used for the heavy lifting and the OpenGL calls (via skia), but the core Flutter library is written in Dart. Yes, that means we will be writing Dart code to write the Widgets/Components on the screen.

Incidentally, I first came across Skia when I found SkiaSharp. Skia itself is a C++ open source 2D graphics library and is used in Chrome, Firefox, Android etc and SkiaSharp is a C# port which is used in Xamarin Forms. But I digress...

So what about the GUI elements? Well, the framework calls them Widgets and provides you with containers, buttons, Forms, List Views, Srollers, etc. It's from these foundational Widgets that you create your own custom controls.

Why dart?

Ughhh. Dart? That was my first thought... Why didn't they choose Kotlin. The last mobile app I wrote used Kotlin which is a very nice language and because it is built on the JVM means you can interface with the large set of existing Java libraries out there.

So, at first I was a little disappointed to learn that flutter uses Dart as its primary language. But you know what? After playing with Dart a bit, it's actually a pleasant language.

Now there have been some changes to Dart, since it first came out that I was not aware of. For example, when Dart 1 originally shipped it had optional typing. But thankfully Google saw the error of their ways and for Dart 2 strong mode has been adopted. As Flutter uses Dart 2, this means our code is like C# & TypeScript in that types are required or inferred. This is good news as it means you get all the benefits of static typing.

There are some weird things to get used to though. For example Dart does not have public or private keywords!! Yes, classes can't have private variables!! Coming from other languages where the keywords "public, protected & private" are the norm, these keyword omissions just seems weird to me. There are other oddities like multi-threading that I won't get into here. However, for the most part, if you're coming from JavaScript, Java or C# then Dart is a pleasant language to code in.

I still kinda think it's a shame they didn't go with a more powerful language like Kotlin, especially as JetBrains are working on Kotlin Native which would have solved the iOS side of the story. However I suspect the choice to use Dart was a political one as Google own and control Dart so there won't be any nasty surprises further down the road (cough Oracle)!

Code Sharing versus UI Sharing

Here's the really cool thing I love about Flutter. And that's the fact that the user-interface you design and write, is shared across Android and iOS. Which, when you think about it, makes sense... I mean all it is doing is spitting out the same pixels to the screen. The framework doesn't care that the screen in question just happens to be an iOS screen with a notch on the top! The frameworks game-loop is just calling its OnDraw function.

If you want the same brand theaming across iOS and Android this is great, however Flutter is also platform-aware so if you want to have apple style widget on iOS you can! The choice is yours!

When Xamarin first came out their selling point was that you wrote the business-logic once but then had to write the UI layer twice. In the early days the benefit to developers was more about the "Code Sharing" aspect of the platform rather than the "UI sharing". Of course, since then, Xamarin have introduced Forms which aims at helping developers also write the UI code once.

In comparison, it seems to me that the biggest benefit of Flutter is the "UI sharing" aspect of the framework and the code sharing is secondary. This nicely brings me on to API's...

Accessing Android & iOS APIs - Plugins!

One of the big selling points of Xamarin is that they give you access to the "full spectrum of functionality exposed by the underlying platform". Basically, any APIs you can call from a native iOS or Android app, you can call with Xamarin. It exposes all those native APIs from C#. From a developers point-of-view, you gotta say, that's pretty cool.

The Flutter folk have gone down a different path. Instead of exposing every conceivable API you could call, they allow you to write plugin packages that you can share with the community, These plugins allow you to write dart code that interfaces with a specific set of APIs. This means you can always open up the iOS or android sub-folders and write as much Obj-C/Swift or Java/Kotlin code as you like.

I think anyone who takes even a cursory glance at Flutter will agree that they have got the UI side down. But I think the crucial part of the Flutter story is going to be the interop with the native APIs. For example, if you choose Xamarin, you know the platform APIs are exposed and available for you to call from C# but with Flutter, you are either going to have to rely on the community to provide a plugin that interfaces with the APIs you want or roll up your sleeves and write the platform specific code yourself (and potentially twice).

It's going to be interesting to watch how this side of the story unfolds for Flutter.

Reactive Views & Hot Reloading

Flutter uses the same model as React for building UI. If you think about visual designers like we have had with the likes of Winforms, WPF, Android & iOS, they all focused on the visual layout of the UI alone. One thing that stood out for me straight away was that there isn't a visual designer for flutter. No XAML or XML layout editor.

With Flutter though, you write your UI directly in code! Now before you throw your teddy-bear out the pushchair, it turns out that this isn't a problem because of the fast hot-reload. Essentially the code you change is instantly reloaded in the Emulator which means you get instant feedback.

Here is the obligitory screenshot from the main Flutter website, showing the hot-reload in action:

There is also something called the Widget Inspector which is very cool. Whatever part of the screen you touch, it will tell you what class that region of the code relates to. It allows you to jump straight from the UI to the code!

Building Blocks of an App

There are lots of great articles on how to get started with Flutter, (like these ones here, here & here) but once you have got to grips with all the Widget aspects of the framework, you start to think and have questions about the other building blocks of a mobile app, like I did.

Here are some of the things I have noticed after reading up on Flutter.

Coming from C# / Java where we have great JSON libraries like Json.Net or Gson, I was a little taken aback to realise there was nothing equivalent in Dart. Also, because the official docs mention that runtime reflection is disabled in Flutter the chances of getting a library like Json.Net or Gson are slim to none! Instead, this article explains what it is like to perform JSON serialization/deserializtion in Flutter.

For network comms, the last app I wrote made use of the excellent OKHttp library. Of course, there is no equivalent in Dart. If you intend to do anything like certificate pinning you can make use of this plugin or write the plumbing code yourself.

If you want to make use of a local database, thankfully SQLite is available via the sqflite plugin. This is great write-up on how to incorporate it in your app.

If you are familiar with MVVM pattern, then this article here could be a useful read which uses the ScopedModel plugin. This allows you to automatically update the Widgets in the tree when the model is updated.

If you plan on writing an app that makes use of background notifications, then the latest beta version of Flutter now has a solution. The sample code for background execution of Dart code can be found here.

If you are looking at integrating a map in your application then using Leaflet could be an option until the Google Maps plugin is properly supported. (At the moment, it does not support iOS). There is a good write-up on how to use Leaflet here, and here. The plugin is available here.

At some point you might want to include a webview as part of the app. Yes, there is a plugin for that! This article has a good write-up here and the plugin can be found here .

Finally, I've been looking at what is available with regards to client-side encryption. If you have a need to encrypt/decrypt data using AES/SHA25 then this plugin library uses native platform implementations on both Android/iOS.

Wrapping Up

I am not sure when Flutter is going to hit 1.0. There is still over 4,000 open issues on Github so I guess there is a way to go before they iron out all the remaining severe issues, however, the framework has a lot of promise and is very exciting. Flutter is definitely one to watch!

hit counter

Contact Me:  ocean.airdrop@gmail.com

Sunday 7 October 2018

Installing RabbitMQ on Windows

I really like RabbitMQ!

If you have not come across RabbitMQ before, it's a messaging system that enables you to seperate your system out to communicate and send data between services or even other systems. If you want to ensure your system meets your reliability, scalability and performance requirements for today but also for tomorrow, then a messaging system like RabbitMQ is a great shout.

In a nutshell, RabbitMQ provides a way of architecting your system so that you can write small services that focus on one job that are scalable to meet your performance requirements.

What does that mean?

Well, when you are designing a large system, there are going to be different parts of the system that will want to communicate with each other. For example, sending commands/actions from one system to another or even just sending notifications.

So, instead of writing your traditional, monolithic application, which is just one big codebase, message queues enable you to write small services. These services are usually lightweight and focus on one job! So, for example, you could have a ProcessOrder Service and an AlarmHandler Service, etc.

But how do these services talk to each other? Well, that’s where message queues and RabbitMQ comes in.

RabbitMQ is the glue that enables asynchronous communication between each of our business layer components. At its core, RabbitMQ is a FIFO (First in, First out) message queue and its fast! - The messages are transient meaning they are not stored forever and at some point are picked up for processing. In addition to all this, RabbitMQ can guarantee that messages will be delivered to the destination no matter what happens!

Writing software this way has got lots of benefits. If one of the services is under heavy load, we can spin up extra copies of the service (even across more machines) to cope with the load (scalability). This is called horizontally scaling and means each service can scale independently of one another.

More importantly, because these services are independent from one another (and not in some monolithic application), we can alter the functionality of one service in isolation of the others knowing our change will only affect this service. This makes for a more maintainable system.

If you need to connect lots of things together, have great performance and need something which is robust and production-ready you can't go wrong. As I said, I really like RabbitMQ!

Best of all, and this is the amazing bit... it's free!

Installing RabbitMQ on Windows

RabbitMQ is available for install on both Linux and Windows. As I have recently installed RabbitMQ on a Windows system, I thought I would write up the installation process while it was still fresh! My perception is that RabbitMQ is better supported on Linux than it is on Windows and there are a couple of gotchas when installing on Windows.

Step 1 - Set Base Directory

Okay, before even installing RabbitMQ, the first thing we need to set up is the RABBITMQ_BASE environment variable. The reason for this, is by default the RabbitMQ database/queues are saved to disk on the C: drive, in the directory %APPDATA%\RabbitMQ. As I mention in this StackOveflow answer, this just seems wrong to me. So, just to make sure we have space, we set this variable up to force the database to be held on the D: drive.

Step 2 - Installation

With the RABBITMQ_BASE environment variable setup, we can now actually kick off the installer process. Now, RabbitMQ depends on Erlang which means we are going to need to install Erlang fist before RabbitMQ.

At the time of this blog post, I am downloading RabbitMQ Version 3.7.8 and this version supports Erlang 19.3.6 up to 21.0. You can find out which version of Erlang RabbitMQ supports by going here.

Once installed, you will be able to fire up the RabbitMQ Command Prompt

To confirm everything installed fine, run the status command from the RabbitMQ command line

rabbitmqctl status

Step 3 - Setup Admin User

By default, RabbitMQ comes with the guest/guest credentials. Let's first take the time to setup an administrator account. From the RabbitMQ command line run the following commands:

rabbitmqctl add_user adminuser password1
rabbitmqctl set_user_tags adminuser administrator
rabbitmqctl set_permissions -p / adminuser ".*" ".*" ".*"

You will be able to change the password from the web interface, but if you need to change the password from the command line, type:

rabbitmqctl change_password adminuser password2

Step 4 - Enable the Web Management Interface

By default RabbitMQ gets installed with everything off. Next, we need to enable the web interface.

rabbitmq-plugins enable rabbitmq_management

From the same machine you should now be able to log onto the management interface by visiting http://localhost:15672 and logging on with the admin user we previously created.

If at any point you need to disable the web interface, you can do so with the following command:

rabbitmq-plugins disable rabbitmq_management

Step 5 - Open Ports on Windows Firewall

To be able to access the management interface externally, we need to open some ports on the firewall. Run the following commands:

netsh advfirewall firewall add rule name="RabbitMQ_15672" dir=in action=allow protocol=TCP localport=15672
netsh advfirewall firewall add rule name="RabbitMQ_15672" dir=out action=allow protocol=TCP localport=15672

Whilst we are here, we also need to open port 5672 to allow clients to access RabbitMQ and add or remove work to the queues:

netsh advfirewall firewall add rule name="RabbitMQ_5672" dir=in action=allow protocol=TCP localport=5672
netsh advfirewall firewall add rule name="RabbitMQ_5672" dir=out action=allow protocol=TCP localport=5672

If you need to delete these rules at a later date, run the following command:

netsh advfirewall firewall delete rule name="RabbitMQ_5672"name protocol=TCP localport=5672

The next thing you need to do is open the management port 15672 on the Windows firewall, so that you can access the management interface from an external machine.

Step 6 - Setting up the config file

The next thing I did was to setup the config file. By default, RabbitMQ doesn't come with a config file so you will have to set one up yourself. You can find an example of the new rabbitmq.conf file here. If you read the documentation, it talks about setting up a new environment variable named RABBITMQ_CONFIG_FILE. However, it looks like there is a bug in the windows version of RabbitMQ as I could not get it to pick up the config file from this location.

So, as a work-around copy the config file to the RABBITMQ_BASE directory (which in my case is D:\RabbitMQBase).

Now, to get RabbitMQ to pick up the config file on Windows, we also need to additionally stop and restart the RabbitMQ windows service using the following rabbit commands:

rabbitmq-service stop
rabbitmq-service remove
rabbitmq-service install
rabbitmq-service start

When we then take a look at the log file after our restart, we can see that it has picked up our config file:

Now that we have the config file setup, we can specify things such as maximum memory usage and disk limits. For example, the following config setting pins the maximum memory usage to 1GB of RAM.

vm_memory_high_watermark.absolute = 1024MB

At this point, that's it! We have successfully installed RabbitMQ on our windows system!

RabbitMQ Diagnostics & Monitoring

Now, because a messaging system such as RabbitMQ is such a crucial component of the system, it would be good if we could be notified when there was a problem.

For example:

  • One of the Rabbit MQ nodes goes down
  • One of the queues stops receiving data
  • There are no consumers moving messages off a queue
  • The number of messages in a queue exceeds a certain number

That kinda thing. Thankfully, RabbitMQ has an API that allows you to query the service. In a browser, you can query the interface and get JSON data back about the service. For example:

Here is an example of the different endpoints you can programmatically call:

http://adminuser:password1@127.0.0.1:15672/api/
http://adminuser:password1@127.0.0.1:15672/api/queues
http://adminuser:password1@127.0.0.1:15672/api/queues/%2f/queue-name
http://adminuser:password1@127.0.0.1:15672/api/connections
http://adminuser:password1@127.0.0.1:15672/api/consumers

For a full list of all the available API endpoints, see this page a href="https://pulse.mozilla.org/api/">here/a>


Wrapping Up

That's it! Job done!


Contact Me:  ocean.airdrop@gmail.com

Sunday 30 September 2018

Outputting HTML Content to PDF in C#

If you type "C# PDF Library" into google you will find there are lots of different offerings out there.

My search turned up IronPDF which costs $399. We have got EOPdf which costs $749 or abcPDF at $329, Hey, what about ExpertPDF HtmlToPdf Converter which is $550.

But what about free?

Well after a bit more interweb searching, I came across HTML Renderer for PDF using PdfSharp. Now, I have previously used the HTMLRenderer in previous projects such as my own DataGridViewHTMLCell project so naturally, it was my first port of call.

But when testing out this library I hit a snag...

You see I want to be able to create bookmarks in PDF as well as forcing page breaks in HTML and, unfortunately, during my testing I was not able to to achieve this using "HTML Renderer For PDF". It seems, if all you want to do is throw some HTML together and convert it to PDF and don't care about formatting, then HTML Renderer will be perfect for you, especially as its light-weight, performant and 100% managed code.

And so, my search continued!

..I guess at this point, I should back up and explain the requirements/features I am looking for in my PDF library

  • The ability to output to PDF (which is err.. self-explanatory!)
  • More importantly, the ability to output HTML to PDF
  • The ability for library to be used in Click Once App
  • The ability to create bookmarks in PDF Documents (This is important)
  • The ability to force page breaks in HTML (This is important)
  • The ability to set page orientation (landscape, portrait)
  • The ability to set page size (A4)

Now, before continuing I should say HTML Renderer is built on PdfSharp which looks very good and in theory should allow me to create bookmarks and page breaks but I could not get HTML Renderer to work for me. I didn't spend too much testing however and your mileage my vary.

OpenHtmlToPDF

Now, if you do enough digging eventually you will come across wkhtmltopdf. It's an "open source command line tool to render HTML into PDF using the Qt WebKit rendering engine" and it seems a lot of PDF libraries just sit on top of this library and leverage its functionality.

There are a number of libraries that make use of wkhtmltopdf such as NRecoPDF but what I liked about OpenHtmlToPDF is that the wkhtmltopdf.exe is held inside the OpenHtmlToPDF DLL as an embedded resource. This means, when it comes to apps that use Click Once deployment, everything just works as you don't have to manually specify the .exe as part of your deployment.

So, what does the code look like? Well, first install OpenHtmlToPDF via nuget and then run this simplest example:

private void TestOpenHtmlToPDF(string html, string fileName)
{
    var pdfBytes = Pdf.From(html).Content();
    System.IO.File.WriteAllBytes(fileName, pdfBytes);
}

Page Breaks

Like I mentioned, one of my requirements was to be able to programmatically force a page break from HTML. Fortunately, it wasn't long before I stumbled across this StackOverflow post that helped me here.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <title>Paginated HTML</title>
    <style type="text/css" media="print">
        div.page {
            page-break-after: always;
            page-break-inside: avoid;
        }
    </style>
</head>
<body>
    <div class="page">
        <h1>This is Page 1</h1>
        <p>some text</p>
    </div>

    <div class="page">
        <h1>This is Page 2</h1>
 <p>some more text</p>
    </div>

    <div class="page">
        <h1>This is Page 3</h1>
        <p>some more text</p>
    </div>
</body>
</html>

With the above HTML template, and the following code snippet below which sets the wkhtmltopdf setting "web.printMediaType" to true:

private void TestOpenHtmlToPDF(string html, string fileName)
{
    var pdfBytes = Pdf.From(html)
                      .WithObjectSetting("web.printMediaType", "true")
                      .Content();

    System.IO.File.WriteAllBytes(fileName, pdfBytes);
}

OpenHtmlToPDF produces the following PDF file. Notice that the bookmarks are automatically generated from HTML <H1> tags and that the content is separated across pages. Exactly what I was looking for.

In fact you can access any of the underlying wkhtmltopdf settings using code like the following:

private void TestOpenHtmlToPDF(string html, string fileName)
{
    var pdfBytes = Pdf.From(html)
                      .WithObjectSetting("web.printMediaType", "true")
                      .WithGlobalSetting("size.paperSize", "A4")              
                      .WithObjectSetting("web.printMediaType", "true")       
                      .WithObjectSetting("footer.line", "me a footer!")
                      .WithObjectSetting("footer.center", "me a footer!")    
                      .WithObjectSetting("footer.left", "left text")        
                      .WithObjectSetting("footer.right", "right text")       
                      .WithMargins(0.5.Centimeters())
                      .Content();

    System.IO.File.WriteAllBytes(fileName, pdfBytes);
}

There are lots of settings which can be passed to wkhtmltopdf. You can find a listing of them here.

Wrapping Up

All in all if you want a bit more control over the HTML/PDF content you produce then OpenHtmlToPDF and wkhtmltopdf might be the ticket. Its a thumbs up from me!

web counter
Contact Me:  ocean.airdrop@gmail.com

Saturday 23 June 2018

Auto Updating an Android App outside the Play Store

In my previous post, I explained how I was writing a private Android app that is only intended for personal use (basically a hobby project). Because of this, I do not intend to release it in the Google Play Store..

But that brings up an interesting question:

How am I going to update this app over time?

One of the benefits of hosting your app in the Google Play store is that you get the ability to auto-update your apps (amongst other things like in-app billing etc). But, as the official documentation explains, there are many ways you can distribute your Android app including:

  • Distributing through an app marketplace
  • Distributing your apps by email
  • Distributing through a website
  • This is an extra bullet point!

This blog post explains the steps I went through to get my Android app to auto-update via a website. In a nutshell, I wanted the app to be able to:

  • Check a website to see if an updated ..apk is available
  • If so, give the user the option to download the updated .apk
  • Start the install process

To break that down a little bit more, I needed to:

  1. Extract the app version from the embedded resources in the Android App
  2. Create a new WebAPI Endpoint that returns latest version of app and MD5 hash of the .apk
  3. Add the .apk file to IIS and setup Mimetype for successful download
  4. Create about page in Android app with a "check for updates" button
  5. Call the version API to see if the server has an updated version of the app available
  6. Call the web URL that points to the .apk file and download it using OkHttp
  7. Once downloaded, compare the hash of the file with the expected hash given by the API
  8. If sucessful, kick off the install process.
  9. Et Voila

Let's dig into the main areas of it..

App Version Number

The first thing we need to do on the Android side is for the App to have the ability to check its own version number.

The official Android page on versioning talks about the use of the versionCode number which can be used to track the app version. This integer is stored in the build.gradle file

and looks like this:

defaultConfig {
   versionCode 2
   versionName "1.1"
}

From code, we can access the integer using the following code snippet:

try { 
   PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);         
   String version = pInfo.versionName; 
} 
catch (PackageManager.NameNotFoundException e) 
{ 
   e.printStackTrace(); 
}

Simples!

ASP.NET WebAPI Endpoint

Now that the Android app can retrieve its own version number, we needs to be able to call a WebAPI endpoint that returns the latest app version from the server to compare against. Something like:

[HttpGet]
public int GetCurrentAppVersion()
{
    var version = Convert.ToInt32(ConfigurationManager.AppSettings["AndroidAppVersion"]);
    return version;
}

This simple function is just reading the app version from the web.config file:

<appSettings>
    <add key="AndroidAppVersion" value="3" />
</appSettings>

..however it might be better suited for this field to be held in a database table somewhere so it can be easily updated. As it stands, I need to alter the web.config file every time I update the app!

Add the .APK file to IIS

The next job is to add the latest copy of the android .apk file to IIS. For this you simply copy the .apk file into the wwwroot directory.

Once you have copied the .apk to the root of the website directory, we need to allow IIS to download the .apk. For this you then need to add the following MIME Type to the web.config file:

 <staticContent>
        <mimeMap fileExtension=".apk" mimeType="application/vnd.android.package-archive">
 </staticContent>

Another way to do this would be to manually add the MIME Type using IIS Manager but I think using the web.config is the better option because it makes the solution more easily deployable.

Once you have done this, we can test the endpoint to make sure we can download the .apk file using a browser. The rationale behind this test is that if we can download the .apk file manually, our Android app will also be able to download it.

Downloading the .APK file using OkHttp

The next step is to download this .apk file from the Android app using the OkHttp library. Using Okhttp makes downloading a binary file mega easy. The following code is asynchronous and is very efficient . Once the file has finished downloading the onResponse function is called which saves the .apk file to the cache directory.

private fun downloadAPK() {

    toast("Please Wait.... Downloading App");

    val client = OkHttpClient()

    var apkUrl = "http://192.168.0.18:801/oceanairdrop.apk";

    val request = Request.Builder()
            .url(apkUrl)
            .build()

    client.newCall(request).enqueue(object : Callback {

        override fun onFailure(call: Call, e: IOException) {
            e.printStackTrace()
        }

        @Throws(IOException::class)
        override fun onResponse(call: Call, response: Response) {

            val appPath = getExternalCacheDir().getAbsolutePath()
            val file = File(appPath)
            file.mkdirs()

            val downloadedFile = File(file, "appUpdate.apk")

            val sink = Okio.buffer(Okio.sink(downloadedFile))
            sink.writeAll(response.body()?.source())
            sink.close()

            m_fileLocation = downloadedFile.toString()

            this@ContactInfo.runOnUiThread(java.lang.Runnable {

                // UI Code 
                toast("Successfully Downloaded File");

                try {
                    if ( m_fileLocation != "")
                    {
                        val mimeType = "application/vnd.android.package-archive"
                        val intent = Intent(Intent.ACTION_VIEW)
                        intent.setDataAndType(Uri.fromFile(File(m_fileLocation)), mimeType)
                        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 
                        startActivity(intent)
                    }
                    
                    // close activity
                    finish()
                }
                catch (ex: Exception)
                {
                    Utils.LogEvent("AppUpdate", Utils.LogType.Error, ex.message.toString())
                }
            })
        }
    })
}

Once the .apk file has finished downloading, we need to launch it which will install it for the user. The code that runs on the UI thread is responsible for installing the .apk:

val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(Uri.fromFile(File(m_fileLocation)), "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)

FileUriExposed exception

Now, there is one little problem with the above intent code which kicks off the install process. - The setDataAndType no longer works if you are targeting API 24 and above (Which is Android 7.0 - Nougat). If you are targeting API 24 and greater you will get a FileUriExposed exception. The new approach for this, is to use the new FileProvider class to launch the new app.

However, to cheat and side-step this issue you can call the following function on application start-up which will allow the proceeding code to work. Please see this reference post here for more information.

private fun enableLaunchAPK() {
   if (Build.VERSION.SDK_INT >= 24) {
       try {
           val m = StrictMode::class.java.getMethod("disableDeathOnFileUriExposure")
           m.invoke(null)
       } catch (e: Exception) {
           e.printStackTrace()
       }
   }
}

Wrapping Up

That's it.... All works. I now have an application that can auto-update. Now I just need to find some time to actually... you know... Update the app!


Contact Me:  ocean.airdrop@gmail.com

Sunday 20 May 2018

Android, Self-Signed Certificates and OkHttp

Just recently I have been writing a private Android application using the latest freshness that is Kotlin.

Of course, like all mobile applications, it makes heavy use of HTTP requests, sending data back and forth between my app and the back-end API. Because this app is private, it will never be released in the Google Play store and the back-end server will not be publicly available on the internet. The server is a private home web server on an internal network (think intranet) and the application will only contact it over my home WiFi.

Did you know that Sensitive Data Exposure is still on the 2017 OSWASP top 10 list? It's currently sitting at the #3 spot. The OSWASP folks say:

"Over the last few years, this has been the most common impactful attack. The most common flaw is simply not encrypting sensitive data."

So, as a good developer, my next job was to switch my project to use HTTPS/TLS. That's when I remembered Let’s Encrypt which is a free, automated, and open Certificate Authority. What a great opportunity to try them out!

But I quickly hit a brick wall because Let’s Encrypt is only for public facing web sites that are available on the public internet and the service can only issue certificates for valid DNS names. See here, here, here and here.

As I mentioned, I don't have a valid DNS name (just a static IP address) and this server is not reachable via the internet. So unfortunately, playing with lets Encrypt was out!

...That's when I turned to creating my own self signed certificate.

Creating a Self-Signed Certificate

Now, you can create a self-signed certificate right inside IIS. Here is a handy guide on how to do that. But we are not going to take that route. We are going to use OpenSSL. The reason is, for the Android application to trust our own self-signed certificate we need a .crt file (the public key) to be loaded in to the Android app and IIS only creates .pfx files. You can read up on the differences between .pfx files and .crt files here. Another benefit of using OpenSSL is that you can configure how long the certificate is valid for. By defaut, IIS will only allow you to create a self-signed certificate that is valid for 1 year.

I downloaded the Win32 version of OpenSSL from here but thinking about it, I guess I could have used WSL. With OpenSSL downloaded you can create a certificate with the following command:

openssl req -x509 -sha256 -nodes -days 3650 -newkey rsa:2048 -keyout oceanairdrop_private.key -out oceanairdrop.crt

The above command is all we need to create our self-signed certificate.

When I ran the command, I requested that the certificate be valid for 3,650 days which is 10 years.

To use this certificate with IIS, you need to convert it to a certificate to a .pfx file because IIS only accepts .pfx certs. You can think of the .pfx file as a zip file that contains both the public & private key as well as password to protect it. Next run the following OpenSSL command to generate the .pfx key.

set RANDFILE=C:\OceanAirdrop\.rnd
openssl pkcs12 -export -out oceanairdrop.pfx -inkey oceanairdrop_private.key -in oceanairdrop.crt

You will be asked to provide a password for the file. Choose one and when your finished we will now have the .pfx file on disk

IIS API Host

Now that we have created the certificate, we can now go to IIS and import it. Nice and easy.

As a side-note, initially, when I tested my endpoint I got this error message: Error 0x80070020 when you try to start a Web site in IIS 7.0. It turns out I couldnt start the website because a clash of ports. So, I moved my port number to avoid any clashes.

Now, when I test this all in a browser over https, I get the expected warning that my certificate is unknown ( as it is from an invalid authority ) but it works!

Of course, this will not be a problem as I won't be calling my API endpoint from a browser. My endpoints are going to be called from my android application. This is what needs to trust my new certificate, not a browser.

Android and OkHttp

Now that my self-signed certificate has been created, I need to get it working in my Android app.

I am using the OkHttp library in Android for my applications HTTP requests. It's nice and simple to use. Before making any changes to the code, OkHttp errors with the exception: CertPathValidatorException when I attempt to call one of my endpoints. Now lets fix the code by getting the app to trust our new certificate.

This is where we need to load our self-signed certificate file and add it to the Android keystore. Open Android Studio, and copy your .crt file into the Android projects res\raw folder.

With the public key available, we can load the key into our android app and add it as a CA certificate. This ensures that application can trust this certificate.

// Load CAs from an InputStream
val certificateFactory = CertificateFactory.getInstance("X.509")

// Load self-signed certificate (*.crt file)
val inputStream =  App.context.getResources().openRawResource(R.raw.oceanairdrop)
val certificate = certificateFactory.generateCertificate(inputStream)
inputStream.close()

In the code above the variable certificate is our public key. Now we need to tell Android to trust that certificate by adding it to the key store and creating a TrustManager that trusts the CAs in our KeyStore.

// Create a KeyStore containing our trusted CAs
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType)
keyStore.load(null, null)
keyStore.setCertificateEntry("ca", certificate)

// Create a TrustManager that trusts the CAs in our KeyStore.
val tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm()
val trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm)
trustManagerFactory.init(keyStore)

Once we have the loaded the key successfully we can create an instance of OkHttpClient passing in the trust manager.

Here is the full code sample below:

fun GetOkHttpClient() : OkHttpClient
{
    // Load CAs from an InputStream
    val certificateFactory = CertificateFactory.getInstance("X.509")

    // Load self-signed certificate (*.crt file)
    val inputStream =  App.context.getResources().openRawResource(R.raw.oceanairdrop)
    val certificate = certificateFactory.generateCertificate(inputStream)
    inputStream.close()

    // Create a KeyStore containing our trusted CAs
    val keyStoreType = KeyStore.getDefaultType()
    val keyStore = KeyStore.getInstance(keyStoreType)
    keyStore.load(null, null)
    keyStore.setCertificateEntry("ca", certificate)

    // Create a TrustManager that trusts the CAs in our KeyStore.
    val tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm()
    val trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm)
    trustManagerFactory.init(keyStore)

    val trustManagers = trustManagerFactory.trustManagers
    val x509TrustManager = trustManagers[0] as X509TrustManager

    // Create an SSLSocketFactory that uses our TrustManager
    val sslContext = SSLContext.getInstance("SSL")
    sslContext.init(null, arrayOf(x509TrustManager), null)
    var sslSocketFactory = sslContext.socketFactory

    // Create an instance of OkHttpClient
    m_client = OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, x509TrustManager)
            .hostnameVerifier(myHostNameVerifier())
            .build()

    return m_client
}

private fun myHostNameVerifier(): HostnameVerifier {
    return object : HostnameVerifier {

        override fun verify(hostname: String, session: SSLSession): Boolean {

            if (hostname == "192.168.0.18") {
                return true
            }

            return false
        }
    }
}

Wrapping Up

That's it.... All works. If you are like me and have moved the port numbers of your API, then don't forget to open the firewall to those ports!


Contact Me:  ocean.airdrop@gmail.com

Sunday 6 May 2018

Excel Interop & C#

If you've ever developed even a small line-of-business application, sooner or later, you know your users are going to ask:

"Erm... This is great and everything but can we get this data exported to excel?"

Now, of course, exporting data to Excel has always been possible and back in the day, you would use COM Interop to create an Excel file using C# but... how do I put this? - Let's just say it wasn't pretty!

Take this small snip of code for example:

private void ExcelTest()
{
     object mMissingValue = System.Reflection.Missing.Value;

     Application excelApp = new Application();

     // Open the file
     Workbook workBook = excelApp.Workbooks.Open(templatePath,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue, mMissingValue,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue, mMissingValue,
              mMissingValue, mMissingValue, mMissingValue, mMissingValue);

     Worksheet sheet = (Worksheet)workBook .Worksheets[1];
}

Notice all those missing values? Your code would be littered with them. Yuk!. - Those missingValue definitions represented "optional parameters" that can be passed through to the API, but even though we wasn't using any of them, we still had to specify all of them.

Of course, that was before the dynamic keyword was introduced with .NET 4.0. Then everything changed.... The above code could be written like this:

private void ExcelTest()
{
   var excelApp = new Application();

   var workBook = excelApp .Workbooks.Open(templatePath);

   var sheet = (Worksheet)workBook.Worksheets[1];
}

That's much better and easier on the eye. The dynamic keyword made interop with COM libraries so much simpler. For all places where an API had took an object the new interop library itself could replace that object with a dynamic.

...Of course that was then. This is now and things are always changing. - Today, if someone asks me to create an Excel file, I head off to NuGet and reach for "EPPlus".

EPPlus

EPPlus allows you to create advanced Excel spreadsheets using .NET, without the need of interop and its very feature rich. What I particularly like about the library is the documentation and samples. It's very well documented and is chock full of example code.

To install it via Nuget, type: the command: Install-Package EPPlus

As a quick example, if your working in C# there is a good chance you already have the app data held in a DataTable. In that scenario, here is a full example of outputting a DataTable to an excel file using EPPlus:

public static void WriteToExcel(DataTable tbl)
{
    var saveFileDialog = new SaveFileDialog();
    saveFileDialog.Filter = "Excel Workbook (*.xlsx)|*.xlsx|All files (*.*)|*.*";
    saveFileDialog.DefaultExt = "xlsx";
    saveFileDialog.Title = "Save As Excel Report";
    saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

    if (saveFileDialog.ShowDialog() == DialogResult.OK)
    {
        FileInfo outputFile = new FileInfo(saveFileDialog.FileName);
                       
        using (ExcelPackage package = new ExcelPackage())
        {
            //Create the worksheet
            ExcelWorksheet ws = package.Workbook.Worksheets.Add("AppTab");

            // Write the datatable into the sheet, starting from cell A1. 
            ws.Cells["A1"].LoadFromDataTable(tbl, true);

            // save our new workbook and we are done!
            package.Save();

            // open the excel file
            System.Diagnostics.Process.Start(outputFile.FullName);
        }
    }
}

Just, so we are on the same page this one line is the main work-horse of this function:


// Write the datatable into the sheet, starting from cell A1. 
ws.Cells["A1"].LoadFromDataTable(tbl, true);

How easy is that? Very nice! There is so much that the EPPlus library can do, and I have only scratched the surface with this teeny-tiny example.

ExcelDNA

Okay, that's all cool but what if you want to go deeper? What if you need to create a bespoke excel function that your users can use to run a business specific formula?

Thats where ExcelDna comes in. I have only found out about this recently but it is a fast and easy way to create Excel AddIns in C# (again, something that used to be a pain in the what-now!)

Again, the library is available via Nuget via the command: : Install-Package ExcelDna.AddIn

Using this library, creating Excel functions is as easy as this:

public static class MyFunctions
{
    [ExcelFunction(Description = "Say Hello to Ocean Airdop")]
    public static string SayHello(string name)
    {
        return "Hello " + name;
    }

    [ExcelFunction(Description = "Lookup From Database")]
    public static int OceanAirdrop(string nameToFind)
    {
        var dbConn = new DBConnectionSqlSvr(@"127.0.0.1", "sa", "password", "database");

        var sql = "select count(*) as [count] from [some_table] where name = " + nameToFind;

        var result = dbConn.ExecSqlCommandScalar(sql);

        return result;
    }      
}

As you can see above, you have the full power of C# and the .NET framework using this library and it is easy-peasy!

I have not really explored ExcelDNA but the documenation for the project can be found here and the github page for the project can be found here

Wrapping Up

As EPPlus has saved my bacon on a number of occasions, I have added to my programmers toolkit!. If you're in a pinch, and need to export some business data into excel I would reach for EPPlus. It's a nice and simple library!

If you have other needs that extend beyond simply creating excel documents from C# perhaps ExcelDna could be the ticket for you.


Contact Me:  ocean.airdrop@gmail.com

Saturday 10 March 2018

OxyPlot Charting Control

The other day, I needed to display a simple time-series chart inside a little tool I was writing. Now, as we know the web has a slew of cool charting controls to pick from including chart.js and amcharts.js which I have used in the past and are great.

But those libraries were out of the question because I needed to include the chart inside a WinForms application.

Now, in the past I played with the Charting Controls from Microsoft and whilst they are good, that suite of controls has not been updated for an ice-age! So I decided to have a look to see what the landscape looks like for charting controls in the WinForms / WPF arena which is where I came across OxyPlot.

OxyPlot is a cross-platform library for .NET and supports WinForms, WPF, Xamarin and UWP (but let's be honest, Who is targeting universal windows apps?). What makes OxyPlot interesting is that their main page says the project is supported by the likes of JetBrains and Xamarin to mention just a few! Those are big names and mean that the project is very well looked after and is very stable and performant.

How performant? Well, it was able to cope with the "100 thousand" datapoints I threw at it (which was much more than I needed). It's very fast!

The documentation can be found here although it is quite patchy in places. For example, the documentation to tell you how to add the control to the VisualStudio toolbox is absent from the docs at the time I was investigating this project. But on the whole, you don't need the docs because the demo app is very comprehensive with literally 100's of examples.

I mean, just look at that Rose Curve!!!

Psst... Come closer. So, between me and you, I have never heard or come across a rose curve before now!!

Code

Getting up and running with plotting a simple a date/time series is pretty easy. I just knocked-up a quick model class to hold the data and added the list to the LineSeries ItemSource property. Here is my code sample in full:

// Step 01: Create a Model class to hold the data
public class ChartDataPoint
{
    public DateTime Date { get; set; }
    public int Value { get; set; }

    public ChartDataPoint( DateTime d, int v)
    {
        Date = d; Value = v;
    }
}

// Step 02: Create the Plot Model
var plotModel = new PlotModel { Title = "Some Cool Chart" };

// Step 03: Setup Y (Left) Axis
plotModel.Axes.Add(new LinearAxis
{
    Title              = "Left",
    Position           = AxisPosition.Left,
    MajorGridlineStyle = LineStyle.Solid,
    MinorGridlineStyle = LineStyle.Dot,
    TickStyle          = OxyPlot.Axes.TickStyle.Outside
});

// Step 04: Setup X (Bottom) Axis
var startDt = new DateTime(2011, 1, 1);
plotModel.Axes.Add(new DateTimeAxis
{
    Position           = AxisPosition.Bottom,
    Minimum            = DateTimeAxis.ToDouble(startDt),
    Maximum            = DateTimeAxis.ToDouble(startDt.AddDays(365)),
    IntervalType       = DateTimeIntervalType.Days,
    MajorGridlineStyle = LineStyle.None,
    Angle              = 30,  // the angle of the text
    StringFormat       = "dd-MM-yyyy",
    MajorStep          = 30, // the positioning of the labels at bottom
    IsZoomEnabled      = true,
    MaximumPadding     = 0,
    MinimumPadding     = 0,
    TickStyle          = OxyPlot.Axes.TickStyle.Crossing
});

// Step 05: Setup the Line Series
var lineSeries = new LineSeries
{
    Title      = "Awesome Series",
    DataFieldX = "Date",
    DataFieldY = "Value",
    YAxisKey   = "megatonnes/day"
};

// Step 06: Populate some data from somewhere!
var chartValues = new List();

for (int nLoopCnt = 1; nLoopCnt < 365; nLoopCnt++)
{
    // generate a random value
    var value = random.Next(1, 100);

    // add data to list
    chartValues.Add(new ChartDataPoint(nextTime, value));

    // increment date by 1 day
    nextTime = nextTime.AddDays(1);
}

// Step 07: Add the values to the line series
lineSeries.ItemsSource = chartValues;
plotModel.Series.Add(lineSeries);

// Step 08: Add the plot model to the control
plotViewChartData.Model = plotModel;

Honorable Mention

Now, I should say, whilst researching charting controls out there I also found LiveCharts which also looks like a great library and something I might use in the future. But when I came to load my test of "100 thousand" data-points LiveCharts coughed and spluttered!! Now, in fairness it wasn't until after that I found that there is a high performant plugin called LiveCharts.Geared which handles more data but by then I had already moved on...Plus LiveCharts.Geared does not look like its free.

Wrapping Up

That's it.. short and sweet. OxyPlot has officially been added to my programmers toolkit! If you need a charting control for your .Net app then give it the once over. It's a nice simple drop-in!


Contact Me:  ocean.airdrop@gmail.com

Saturday 3 February 2018

WebAssembly and C#

I will always remember the day I was shown asm.js running a demo of a game using the Unreal engine... in a web browser, no less!!! - My jaw was on the ground. That was 2014. Little did I know at the time but asm.js would seed the path towards WebAssembly.

WebAssembly (also known as WASM) looks very exciting. The homepage bills it as "a new portable, size- and load-time-efficient format suitable for compilation to the web.". It's being designed "as an open standard by a W3C Community Group that includes representatives from all major browsers.". Basically, it allows statically typed languages to be cross-compiled into a format that browsers can understand and execute. Wow!

Like I say, it looks exciting. For your standard line-of-business web apps, it doesn't sound like it will displace the use of JavaScript when building Web Apps but it will be useful for high performance apps like games or canvas related apps. Even the WebAssembly homepage's demo is a Tank game. In fact, Unity and Unreal have already ported their gaming engines to WebAssembly!

I am just wondering what the future holds for the technology. In five to ten years, could there be off-the-shelf libraries/frameworks (like the .NET Framework) written/compiled to WebAssembly? These libraries would then be consumed by normal JavaScript web apps to execute more performant operations. There are loads of useful C++ libraries out there that the web could benefit from.

By the way, if you want to dive into the nitty-gritty details of WebAssembly, this 5 part series from Mozilla's Lin Clarke is a fantastic diversion of your time.

Browser Support

As you can see from the caniuse.com website, WebAssembly is now supported in all major browsers and here's the thing: WebAssembly is on by default in these browsers, which means you don't have to flip a flag or anything like that to start using it. This means, as of today, there is no friction for end-users.

Language Support

asm.js was originally designed as a way to compile C++ to the web, but one of the advantages of WASM is that you can write it in any language that can cross-compile to WASM. All the major languages look like they will support it in the future including:

  • C and C++
  • Rust
  • C#
  • Java / Kotlin
  • Go
  • ...and even TypeScript which is a bit meta!

As an example of languages that are looking to target WASM, this guy here is maintaining a list of languages that are looking to cross-compile to WebAssembly.

Playing with WebAssembly

As I was reading up on all of this, I thought I would follow the main WebAssembly websites "Getting Started" pages to see just how easy it is to get up and running with a test project.

...But it turns out you can experiment and play around with wasm today using the online WasmExplorer or WasmFiddle websites, however these currently only accept C++ code. This is great because it saves you from having to dust off that C++ compiler.

So I decided to try it out and play with WasmExplorer. I went off and found some random C++ code on the old interwebs that checked if a year was a leap year or not.

This is the C++ code I decided to test out:

#include 
using namespace std;

int main()
{
    int year;

    cout << "Enter a year: ";
    cin >> year;

    if (year % 4 == 0)
    {
        if (year % 100 == 0)
        {
            if (year % 400 == 0)
                cout << year << " is a leap year.";
            else
                cout << year << " is not a leap year.";
        }
        else
            cout << year << " is a leap year.";
    }
    else
        cout << year << " is not a leap year.";

    return 0;
}

But if you paste the above code wholesale into WasmExplorer, you get the following error:

Compiling C/C++ to Wast
Loading: //npmcdn.com/wasdk-capstone-x86/lib/capstone-x86.min.js
Compiling .wast to x86
wasm text error: parsing wasm text at 230:21

It turns out, the wasm compiler doesn't like the cout/cin lines from the standard namespace. That's expected as the std::cin doesn't make any sense in the code above so I did a little bit of code refactoring.

The modified code looked like this:

bool IsLeapYear( int year )
{
    bool isLeapYear = false;
    
    if (year % 4 == 0)
    {
        if (year % 100 == 0)
        {
            if (year % 400 == 0)
                isLeapYear = true;
        }
        else
            isLeapYear = true;
    }

    return isLeapYear;
}

Now, when I compile the above code I now get a successful compile and the ability to download a .wasm file! Nice!

But how do you instantiate this in the browser? Thankfully Mozilla have a great tutorial here. Essentially, you need to load the wasm module, then instantiate the module like this:

var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, wasmImports);

// Now call C++ IsLeapYear function! 
log(wasmInstance.exports.IsLeapYear(2001));

However, when I attempted to run this code locally from a standard directory on disk, I got the following error message regarding the fetch API:

Basically, I needed to serve this file from a simple web server. As I didn't want to mess with Windows IIS I decided to use Python as a quick way to host static content. I'm on Windows, so I fired up the WSL to make use of the Linux Ubuntu command prompt and issued this command:

python -m SimpleHTTPServer 8000

Then, I just needed to navigate to the directory where you want the web server to start from, and was up and running:

For some reason, when doing this my function names were mangled. Instead of IsLeapYear() they were _Z10IsLeapYeari(). I don't know if this is a side-effect of using WasmExplorer or if I had done something wrong but calling the function yields the correct results:

var importObject = {};

function fetchAndInstantiate(url, importObject) {
 return fetch(url).then(response =>
  response.arrayBuffer()
 ).then(bytes =>
  WebAssembly.instantiate(bytes, importObject)
  ).then(results =>
   results.instance
  );
}

fetchAndInstantiate('test.wasm', importObject).then(function (instance) {

 // Now call C++ IsLeapYear function! ( 2000 was a leap year... 2001 was not! )

 console.log(instance.exports._Z10IsLeapYeari(2000));
 console.log(instance.exports._Z10IsLeapYeari(2001));
})

Now when we run the above code we see the results from the calls. The 1 represents the call for the year 2000 and the result of 1 represents the call for the year 2001

C# & Blazor

So, that's all cool but what's the story for .NET and C#?

I am very interested in using C# to target WebAssembly. I use a lot of C# libraries and having the capability to cross-compile them to the browser would be amazing. Using WebAssembly in addition to PWA's could, in the future become the new norm. Imagine pulling down your C# business library in WebAssembly form to run in the browser. You wrote it in C# but its all executable from JavaScript.

While reading up on this topic, I found out about Blazor. This is an experimental C# UI Framework which is apparently highly experimental but a very compelling example of what could be possible in the world of WebAssembly. It makes use of a project named DotNetAnywhere which is a separate port of the .NET runtime

The great thing about Blazor is that you can actually play around with it today!! - The github page for the project can be found here and there is a Visual Studio extension you can install which gives you access to a Blazor application:

When you create the project you are presented with the following solution:

When you run the project you will see this screen, telling you you can navigate to http://localhost:5000 to view the web app.

With the web app looking like this:

The amazing thing about this demo is the fact that C# code is running on the client, in the browser! Here is a snippet of code from this project.

@functions {
    WeatherForecast[] forecasts;

    override protected async Task InitAsync()
    {
        using (var client = new HttpClient())
        {
            var json = await client.GetStringAsync("/sample-data/weather.json");
            forecasts = JsonUtil.Deserialize(json);
        }
    }

    class WeatherForecast
    {
        public string DateFormatted { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF { get; set; }
        public string Summary { get; set; }
    }
}

Under the covers, Blazor uses DotNetAnywhere which is a project I have never heard of before. It's another alternative .NET runtime. However, it doesn't sound like DNA is going to be the future platform for building .NET WebAssembly components as Steve Sanderson (The guy who created Blazor) mentions in this blog post which is worth reading.

However, while this project is just an experiment, it demonstrates the future potential of WebAssembly and C#.

Official C# to WebAssembly Tools

The good news is that the mono team are actively working on a wasm compiler for C#. The name of the tool is called mono-wasm and the project page can be found on github here. It's still early days but something I intend to keep an ear out for. I also found this comment here on example usage of the "mono-wasm" tool.

Wrapping Up

WebAssembly looks great and I am sure it will be another major milestone in the history of web development. Yes, it's still very new and there is a long way to go before it's used for mainstream development. There are also some limitations with it in its current form. For example, at the moment you cannot easily access the DOM from WebAssembly code but improvements in this area are apparently on the road-map!

The idea of writing library code once, using it on the server-side, then compiling and porting for use on the web really resonates with me. I think, if we fast-forward 5, 10 years, once WebAssembly is well established, it is going to have a huge part to play in the future of WebApps.


Contact Me:  ocean.airdrop@gmail.com

Popular Posts

Recent Posts

Unordered List

Text Widget

Pages