Implementing The Functionality Of A Large Silverlight Application In New Technology – Part 1 – Technology Choices

The challenge

Optimium Health delivers and supports a workflow guidance tool. The tool is composed of multiple servers performing such functions as document production, eFax generation, eMail generation, and on-demand report support. An additional component is the user interface which is used both by end users and system administrators. The user interface and the product is referred to as Optimi$er.2012.

The environment of the server is Microsoft Windows Server and the user interface is a Microsoft Silverlight application hosted in Internet Information Services (IIS) and deployed in Microsoft Internet Explorer. Silverlight enjoyed great popularity particularly for video streaming (2008 Summer Olympics in Beijing, 2010 Winter Olympics in Vancouver, 2008 political conventions, Amazon Video & Netflix [Source: Wikipedia]).

The Adobe Flash plugin dominated and was subject to many security breaches. This was the genesis of a movement away from browser plugins. Microsoft announced in July 2015 that Silverlight End Of Life (EOL) would be October 12, 2021.

Replacing a large application with an extensive user interface with backing logic became a strategic concern but not one that overrode the necessity of enhancing and extending the Silverlight client.

Initial technology candidates

An initial survey of browser client technologies performed in 2018 resulted in a dismal set of options.

AngularJS was a client library written in JavaScript that was initially developed in 2009; Although still supported, it was superseded by Angular. AngularJS and JavaScript were deemed too low level with primitive tooling, a type unsafe environment, and lowering popularity due to the release of Angular.

Angular V4 was the latest in a TypeScript rewrite of AngularJS. Tooling was still relatively primitive but at least the language was type-safe.

Aurelia was a new Typescript library favoring convention over configuration. It had no track record as a useful library in actual use however, the creators had a successful previous library (Durandal) and were bent on radically improving the implementation.

Uno platform was released in early 2018. It was a multiplatform tool supporting Windows desktop, Android, iOS, and web browsers. Developed as an internal tool at nVentive, it was later open-sourced.

A choice is made

A decision was made in early 2018 to prototype a client replacement with Angular V5. Basic functionality was created. Data support was a large ‘sticking’ point with the conversion from the C# types supported by the server and the JavaScript types.

There was enough “friction” between the language types to make the examination of other frameworks continue. The plan at this time was to build a minimally viable client during 2019 that addressed one of the four major areas of functionality.

A dark horse appears at the end of 2017 and beginning of 2018

A series of blog posts on the Microsoft Developer site appeared at the end of 2017 and into 2018. These posts detailed an experimental technology (called Blazor) which would bring the .Net environment to the server. This was pretty exciting in that it would remove the ‘friction’ between client and server in much the same way as Silverlight did more than a decade earlier. The major difference was that no plugin was required and the execution could be upon and modern browser (Google Chrome, Mozilla Firefox, Microsoft Edge).

A prototype client was developed and followed the pre-release cadence of the experimental Blazor implementation. The prototype quickly surpassed the Angular prototype in functionality and reliability.

Microsoft emphasized the experimental nature of Blazor throughout 2018 and it wasn’t until October that a full commitment to Blazor was announced. The commitment was to ship the server hosted model of Blazor by the end of 2019 as of October 2019. Blazor became an official part of .Net 3.0 preview 4 in April of 2019.

Switching horses midstream and initial implementation

After the commitment by Microsoft the decision was clear that a Blazor client was to be the preferred technology. The initial implementation would be of the OR Tracking application (a new facet of Optimi$er). The intent was to improve communication and safety of the intra-operative processes.

Optimium Health and a large hospital group partner iteratively developed the tracking application through most of 2019 with a goal of live implementation in Q1 2020. The development process was smooth and we were ready to perform the initial implementation in March of 2020, calling the product Optimi$er.2020;

COVID-19

An odd thing happened while getting ready to implement, that being a global pandemic of a seriously deadly virus with the moniker of COVID-19. All plans for implementation of the OR Tracking application got put on hold while everyone tried to ascertain how to live safely in this new environment.

Finalization of the replacement application

After several months of being stopped in the implementation of the OR Tracking application, the remainder of 2020 and first half of 2021 was devoted to transitioning the Pre-Anesthesia and Surgical Office portions of Optimi$er.2021 (renamed from Optimi$er.2020 because we wanted nothing to do with 2020). The first preview release of Optimi$er.2021 occurred in July. A full transition in two of three departments occurred in October with the third department expecting to finaliz

Blazor: Easily switch between client side and server side execution

Blazor as part of ASP.Net Core 3.0 will be shipping in approximately a month. As a generally available release Blazor is supported with server side execution. Even though client side execution is possible, it will remain in a preview state for at least the remainder of the year. Even if the intent for your project is to target server side there are some useful aspects to host your project in wasm on the client. Notably, the ability to use the browser development tools to understand just what your carefully crafted css is actually doing is priceless. If you are going to target the wasm deployment of your project it is still useful to change to server side for debugging at this point in time.

The source code for this project is available on BitBucket at https://bitbucket.org/MarkStegaOHI/blazor-cse-sse/src/master/. This post will just highlight the key aspects of making the switch easy. It is probably best to clone the repository and follow along using Visual Studio 2019 16.3.0 Preview 3.0 and ASP.Net Core 3.0 Preview 9. The project will be updated to ASP.Net Core 3.0 when it is released.

Solution configurations

There are four configurations in the solution. Using the Visual Studio configuration manager you can choose between debug and release and also between client side & server side execution. The key differences in each configuration is the definition of either ClientSideExecution or ServerSideExecution and DEBUG or RELEASE defined constants. So making the switch is as simple as choosing the desired project configuration.

Solution projects

The names of the projects may seem a bit odd; Just understand that this project was pared down from a very large project ‘in progress’ and in the large project the names make sense. The solution is architected in an MVVM style. Most of what appears in the demo project is simply the collection of view components in their simplest form.

GeneralComponents

This project is a Net Standard 2.0 Razor Class Library and implements the UI and backing logic. OptimiserComponents contains the usual Blazor suspects of MainLayout.razor, NavMenu.razor, and the _Imports.razor files as well as other useful components. These projects do not change with the server or client side execution.

Optimiser.Blazor

This project is the Blazor stub defined by program.cs & startup.cs with the packages of “Microsoft.AspNetCore.Blazor” and “Microsoft.AspNetCore.Blazor.Build”. It is only invoked for a client side execution, it is totally ignored for server side execution.

Optimiser.Web

This project is an ASP.Net Core 3.0 server. It uses the defined constants to determine if it is going to host the Blazor project on the server or to simply act as a launch pad for the client side assets. In real life the server presents a REST api for use by the client in either mode. The key to the switch is in startup.cs where the methods Startup and Configure are customized via the defined constants. This project is always the startup project in VS.

Further enhancements

It would be easy to add the development web server and a copy of the wwwroot folder from the Optimiser.Web project to the Optimiser.Blazor project. This would allow a third ‘mode’ of execution which would be to select the Optimiser.Blazor project as startup. But since that is just another client side execution scenario it is only mentioned here as a possibility.

Blazor: Two way data binding workaround with date input

Blazor is an experimental framework that implements many essential elements of a C#/HTML/CSS framework. See https://blazor.net/index.html for details.

Two way data binding is available for many elements but two notable missing elements are the input elements radio buttons and  dates as of Blazor 0.5.1. The radio button issue has a clean workaround by jsakamoto in https://dev.to/j_sakamoto/workaround-how-to-two-way-data-binding-of-radio-button-input-with-blazor-spa-v050-31fd. This post offers a workaround for dates.

Start with a definition of the date field in your cshtml file like:

<input type="date" onchange="@SelectedDateChanged" id="scheduleDate"/>

In the code-behind file define SelectedDateChanged and OnAfterRenderAsync as

        protected DateTime pSelectedDate { get; set; }
        protected async void SelectedDateChanged()
        {
            string selectedDateAsString = await JSRuntime.Current.InvokeAsync("customizationJsFunctions.getSelectedDate");
            try
            {
                pSelectedDate = Convert.ToDateTime(selectedDateAsString);
            }
            catch
            {
                pSelectedDate = DateTime.Now;
            }
            StateHasChanged();
        }


        protected override async Task OnAfterRenderAsync()
        { 
            if (pSelectedDate != DateTime.MinValue)
            {
                string selectedDateAsString = pSelectedDate.ToString("yyyy-MM-dd");

                await JSRuntime.Current.InvokeAsync("customizationJsFunctions.setSelectedDate", selectedDateAsString);
            }
        }

As you can see there are two calls to JSInterop. Define the following script:

    <script>
        window.customizationJsFunctions = {
            getSelectedDate: function () {
                return document.getElementById("scheduleDate").value;
            },
            setSelectedDate: function (selectedDate) {
                document.getElementById("scheduleDate").value = selectedDate;
                return "OK";
            }
        };
    </script>

And with this you have the equivalent functionality of data binding with the input date element.

Silverlight 5.0 and https Extended Validation

I’ve set up a web application for a client and ran into a problem with https Extended Validation. The site design called for use of extended validation in order to provide an extra layer of comfort for the end users. I spun up the site only to have the following displayed in Chrome and Firefox:


ChromeError

FirefoxError

IE was OK:

IEShoodFail


Not a very successful display of the EV work. Chrome was actually quite helpful with an extended message about a file that was downloaded. So it took some work with the Chrome developer tools to discover that the root of the problem was an image that was being downloaded from Microsoft. If you look at the .aspx or .html page created to host a Silverlight app, the Silverlight plugin has an image that is displayed if Silverlight is not installed (<img src=”https://go.microsoft.com/fwlink/?LinkId=161376″ alt=”Get Microsoft Silverlight” style=”border-style:none”/>). This clearly breaks the EV check as information would come from a non-validated site. The solution is simple. Simply host the image on the web site with the desired EV, ala (<img src=”SLMedallion_ENU.png” alt=”Get Microsoft Silverlight” style=”border-style: none”/>)

Now the browsers show up like this:
ChromeGood
FirefoxGood
IEStillBad

So Chrome, Firefox, & IE do the right thing and have the EV shown as the company name in green (URL mostly redacted).

[EDIT 2015-10-02] When this post was written all three browsers showed an EV failure when an element in the HTML was from a non-EV site (April 2012). Retested on October 2015 with current browser versions and the behavior is now correct across all three browsers when EV succeeds. However, IE shows success when both Firefox & Chrome show extended validation issues in the original test. Given that the image is not actually rendered it isn’t really clear which behavior is correct. <ms>