Category Archives: .NET Framework

Positron – HTML 5 UI For .Net Desktop Applications

At CenterEdge Software, the development department recently had management walk into a meeting and drop a bombshell on us. They wanted us to completely rebuild the UI from the ground up and “make it sexy”. Oh, and “make it last until 2025″. Don’t you just love wild management direction?

Well, we scratched our collective heads for a while and tried to come up with a solution. Preferably one that didn’t leave us clawing out our eyeballs, nor made management come asking about how we blew the budget. We came up with three key criteria we had to meet.

  1. We need to leverage our existing .Net code as much as possible.
  2. We need to be able to deliver the UI redesign in phases over time, rather than operate in a completely independent branch for a couple of years.
  3. We need to support the current hardware infrastructure at our 600+ clients, so that hardware upgrades and networking redesigns are not required before upgrading.

What We Aren’t Doing (And Why)

Based on these criteria, our first thought was WPF. We could continue writing .Net desktop client/server applications to operate our Point of Sale and other local applications. This would allow us to easily maintain our current low-level hardware integrations (read: lots of serial ports and USB serial emulation – ugh). It would also allow us to easily phase in portions of our application as WPF while other portions remain WinForms.

The downside to WPF is the size of the developer pool. There just aren’t that many WPF developers out there, especially great ones, and they tend to be expensive. But what about HTML5 and Javascript? There’s all sorts of great work happening surrounding web technologies and user interfaces. And there’s a much larger pool of developers with these skills for us to draw on.

Looking at HTML5 UI options, we looked at and discarded the two obvious solutions:

  • Convert to a cloud application. We already have cloud components to our suite. But the core on-premise system, if converted, would become too reliant on stable internet connections, and too far from our current architecture to convert easily. This would also be very difficult to implement in a phased manner.
  • Operate an on-premises web server. For our larger clients this wouldn’t be an issue. But a significant portion of our client base are smaller businesses that use workstations as their servers. IIS isn’t an option, and a computer with a couple extra GB of RAM might work for running SQL Express, but not for running the whole application for a half dozen stations.

Can We Have Our Cake And Eat It, Too?

Is it possible to have the best of both worlds? Can we run a desktop client/server application like WPF, but yet build our UI using HTML5? Well, this question stumped us for a bit. But there are systems that do this, like Electron, just not for .Net.

Enter Positron! Positron is a solution for building a .Net desktop application using HTML5 user interface components (rendered using Chromium). It hosts an in-process version of MVC 6 (yes, that’s the new .Net Core flavor), which is then wired in-process to Chromium running within a WPF window.

Fun Facts

  • All requests from Chromium to MVC are handled in-process, there’s no network stack or HTTP involved. This keeps performance and security very high.
  • The window itself is the only WPF involved, the entire window content is the Chromium browser.
  • ASP.Net Core MVC, despite having “Core” in it’s name, isn’t actually .Net Core specific. You can use it in traditional .Net Framework applications as well.
  • All resources (images, views, CSS, JS, etc) are embedded in the DLL, making application distribution easy.
  • Positron even supports Chromium developer tools (via a separate Chrome window).
  • Positron is agnostic about how you build your HTML5 application. We’re currently using using React and TypeScript at CenterEdge. We’re even using Browserify and Gulp to build the JS files. But any web technology will work, pick your favorite flavor.
  • There is currently one significant issue, the Razor view editor in Visual Studio doesn’t recognize the fact we’re working with MVC, so it’s a squiggle fest. I’m sure support for this will be forthcoming, and it works fine after you compile and run. If there are any Visual Studio experts out there, we could use some help with this!

What About Automated Testing?

All the QA and QE people out there are yelling at me now. They’re saying their test frameworks won’t work with Positron. We have a solution for that, too. You’re building an MVC application, just hosting it in-process. There’s nothing stopping you from spinning up a Kestrel server instead to support automated testing over HTTP. Just use Chrome as the test browser for parity with Chromium.

It’s also possible to install plugins in Chromium, so it might be possible to get some of the testing frameworks up and running directly against Positron if their plugin is installed. But we haven’t vetted this out yet.

Open Source

Our specific use case is probably not common. But at CenterEdge we do feel like there is a need for desktop applications with HTML UI. There are many .Net desktop applications that could benefit from the plethora of great UI tools and frameworks available in the web development community. Therefore, we’ve decided to make Positron open source. It’s available on NuGet (there are 4 packages), and the code is available on GitHub.

At this point it’s an early version (0.2.0), and there’s lots of room for improvement. We are already working on integrating this into our application suite, and then learning the pain points to make improvements

We’d also welcome community feedback. And feel free to fork the repo and send back pull requests.

Simplify CSS and Javascript Compression In Visual Studio

I’ve released a new open source tool that performs design-time compression of your CSS and Javascript files in Visual Studio projects.  This can be a big help, since it allows you to easily do it in your project rather than as part of your build/publish process.  And, since it leaves both the compressed and uncompressed versions in place, you can still use the uncompressed version for debugging.

Read more about this new tool or download it at http://btburnett.com/netcompressor.

Create A Self-Signed SSL Certificate In .NET

A problem that I have commonly run into is trying to secure communications using SSL or other encryption for a intranet application. In this scenario, it is unnecessary to have a secure certificate signed by an expensive Internet authority. And often it is intended for deployment in a small-scale scenario where there might not be a Certification Authority running on a Window Server. In this case, you want to create a self-signed certificate and use the thumbprint of the certificate for phishing prevention.

Microsoft does provide a utility, makecert, which can create a self-signed certificate. However, it isn’t distributed with Windows, is command line only, and definately NOT end user friendly. I wanted a method for creating a certificate just by clicking a button, without using a shell calls and distributing a copy of makecert with my applications.

To this end, I created a VB.Net class that calls out to the CryptoAPI and creates a self signed certificate with a 2048-bit RSA key. The certificate and private key are stored in the Local Machine store. In the Local Machine store it can be accessed by system processes and services. I’ve attached an example of the class to this post, feel free to use it as you see fit.

Certificate Creator (2092)

Using Enumerations For Columns With LINQ

One of the great features of LINQ that DataSets didn’t support well is the ability to use enumerations for your columns instead of integers. It can make writing and working with your code a lot easier. This is accomplished by manually setting the Type of the column to the type of the enumeration in the visual designer.

There are two important notes to remember about doing this. First, it takes extra work if you want to use an enumeration that is in a different namespace from the LINQ classes. You must not only include the full namespace, but also the global:: prefix. So “global::EnumNamespace.EnumTypeName” refers to the enumeration EnumTypeName in the EnumNamespace namespace. Secondly, if you want to update the data structure from the database, you have to remember to manually set the Type back to the enum type from integer.

This system works great most of the time, including when performing LINQ queries in your code. However, the one place it doesn’t seem to work well is in the Where clause of a LinqDataSource. If you try to select on the column values of an enumeration column here, you’ll get various exceptions. If you try to refer to the enumeration constants, you get “No property or field ‘x‘ exists in type ‘y‘. I’ve tried various namespace permutations with no success. If you try to use integers directly instead of enumeration members, you get “Argument types do not match”.

The only solution I have found to the problem is to typecast the column and compare to integers. For example, “Int32(ColumnName) == 1″. Personally, I don’t like this solution much because it can cause huge problems if your constants ever change, but it works.

Also, if you are dealing with a Flags enumeration, it gets even worse. I haven’t found any way to do bitwise operations in the Where clause, so you have to compare the column to all possible integers that contain the bits you are interested in.

If anybody knows of a better way to address this issue, please post a comment and let me know. Thanks.

Event Handlers That Do Thread-Safe Invokes

I recently ran into a scenario where I wanted to write a class to do a low-level serial interface to a barcode scanner. When the barcode is scanned I wanted it to fire an event back to the Windows form. The complication was that the SerialPort class provided by .NET 2.0 fires the DataReceived event on an independent thread. In order to fire the event back to the form it needs to be synchronized to run on the thread of the form using the Invoke method.

While this can be done using manual delegates and other methods, they don’t work very cleanly like an actual event handler does for simple development. The fix to this problem is to actually write a custom event handler. The custom event handler implements all of the back end handling that is normally hidden by VB. Here is the example code from the barcode scanner class:

Private _barcodeScannedList As List(Of EventHandler(Of BarcodeScannedEventArgs))
Public Custom Event BarcodeScanned As EventHandler(Of BarcodeScannedEventArgs)
AddHandler(ByVal value As EventHandler(Of BarcodeScannedEventArgs))
If _barcodeScannedList Is Nothing Then
_barcodeScannedList = New List(Of EventHandler(Of BarcodeScannedEventArgs))

End If
_barcodeScannedList.Add(value)

End AddHandler

RemoveHandler(ByVal value As EventHandler(Of BarcodeScannedEventArgs))

If Not _barcodeScannedList Is Nothing Then
_barcodeScannedList.Remove(value)

End If

End RemoveHandler

RaiseEvent(ByVal sender As Object, ByVal e As BarcodeScannedEventArgs)

If Not _barcodeScannedList Is Nothing Then
For Each handler As EventHandler(Of BarcodeScannedEventArgs) In _barcodeScannedList
Dim safeInvoker As ISynchronizeInvoke = TryCast(handler.Target, ISynchronizeInvoke)
If safeInvoker Is Nothing Then
handler.Invoke(sender, e)

Else

safeInvoker.Invoke(handler, New Object() {sender, e})

End If

Next

End If

End RaiseEvent

End Event

The _barcodeScannedList simply stores a list of all of the event handlers that have been registered with the class. AddHandler and RemoveHandler do the process of actually adding and removing those event handlers from the list. The real meat is in the RaiseEvent handler. Instead of simply iterating through the list and firing all of the event delegates directly like the standard handler does, this handler tests to see if the target class of the delegate implements the ISynchronizeInvoke interface. System.Windows.Forms.Control does implement this interface, meaning that all Forms implement it. If this interface is found, then the interface’s Invoke method is used instead of the delegate’s Invoke method. This will synchronize the call onto the delegate’s target’s thread.