Adventures on the edge

Learning new development technologies
    "When living on the bleeding edge - you sometimes have to bleed" -BillKrat

Open Live Writer: how to install plug-ins (work-around)

Source code: BillKrat/OpenLiveWriter (CodeSnippet)

lw-001-codesnippet

It was great news that the Live Writer application was released as open source – initially there was some momentum behind it and as a result we have source code that we can easily compile in Visual Studio.  Unfortunately, the revisions made rendered the existing plug-ins useless with no readily available documentation or process for being able to utilize them.  This prompted me to start an adventure so that I could get my favorite “Code Snippet” plug-in back.

The source branch I reference in above link is my fork on GitHub where I compile it under Visual Studio 2017 after making some tweaks; more specifically – fixed issues that crashed the application’s internal processing. 

In a nutshell to get the “Code Snippet” plug-in working you have to copy the SharedDll contents (OpenLiveWriter.BlogClient.dll) to the click once application folder (instructions below) and then copy the SharedInstall contents into the “Open Liver Writer” plug-in folder.

lw-002-pluginFolder

There are a couple of issues at play here that cause our plug-in dilemma:

  1. An exception in the blog providers causes the plug-in logic to be bypassed
  2. The plug-ins are compiled with an API that no longer exists – the namespace has changed.

Exception is thrown that causes logic to be bypassed (if applicable - above works with latest release)

If you were to download the source for my Visual Studio 2017 branch (reference link above) and search for “BillKrat” you will find the minor revisions made that permitted the application to run without internal crashes.  Note: I did provide a pull request

Below you’ll see that I remarked out a provider that was causing an exception to be thrown bypassing the logic that checks the Plug-ins folder (shown in image above).    To resolve this you’ll need to replace the OpenLiveWriter.BlogClient.dll.
image

To replace the dll in the click-once application you can simply launch the application, load the Task Manager, right click on the executing application, and select “Open file location” as shown in the image below.   Once opened in the file explorer you can replace the OpenLiveWriter.BlogClient.dll.  Upon subsequent usage of the click-once application you will be able to load plugins from the plug-in folder.

lw-004-taskmanager


The plug-ins are compiled with an API that no longer exists

Once I could get the dll to load from the open source code, it then crashed because the WIndowsLive.Writer.Api is no longer available, the namespace was changed to OpenLiveWriter.Api.  This effectively breaks all existing plug-in code.   My initial knee-jerk reaction was to get .NET Reflect (version 6 was a free version if you can still find it on the internet) and have it extract the code from the existing dll.  I then removed the outdated reference, referenced the new OpenLiveWriter.Api project, fixed minor compile issues (from Reflector) and Walla!  I had a functional code snippet plug-in.   I later found that there are numerous open source plug-ins for Windows Live Writer that can downloaded, retro-fitted with the new OpenLiveWriter.Api and dropped into the applicable folder without having to use Reflector. Note: as of this writing I only use the Code Snippet plug-in.

lw-005-reflector

MVPVM over MVVM

As I design the Visual Studio project structure for my new open source Contact Manager, which I am writing for a local religious organization pro bono, I have to keep a few things in mind:

  1. My vision statement of “create a contact management system for the web, desktop, and phone utilizing the same code-base.  It should be extensible so that additional modules, such as a donation module, can be easily added reusing the existing infrastructure and components”
  2. The contact manager utilizes user information – these are components that will be reusable across future modules as well as applications.  We’ll want to place these components in a Gwn.Global.xxxxx projects (figure 1).
  3. The desktop and web applications can access the business [and thus data access layers] directly – important because the client wants to have an on-site SQL database as well as a “cloud” based SQL database (they will be synchronized).   The desktop app will be configured for the on-site database and the web application for the cloud database (figure 3)
  4. The mobile applications: tentatively Google Kotlin for Android, and Apple Swift for IOS, will be mainly presentation layers consuming a service layer for the cloud database (figure 2).

The use of MVVM over MVPVM has been a debate that I usually have with team members during initial planning, in some cases I win, other times I lose – I’m a team player so when the decision is made, I roll up my sleeves and make it work.

While planning/diagramming the project structure that  I will use for this solution, it quickly became apparent why the Model-View-Controller (MVC) Presentation Model had architects of the day wanting to evolve to the Model-View-Presenter (MVP) – Martin Fowler discusses it in his article on GUI Architectures.  

Before continuing… What does Presentation Model have to do with MVVM?   This tidbit of information is the contextual glue that bridges the gap between our early architects with todays – we lack a common core of experience so we missed this important lesson.  John Gossman, the founding father of MVVM noted that MVVM is a WPF-specific version of the PresentationModel Pattern, versus the ApplicationModel pattern which permitted the view model to access the view – seen as a “a bit of dirty work”.  The PresentationModel pattern does not allow access to the view as it would prevent the reuse of the view model with other views, which is a well understood MVVM pattern rule. 

When we view the power of separated presentation, we have to do so within the context of MVP versus MVVM, because as our early architects taught us – MVP solves the problems of MVC.   One such problem rears its ugly head in the diagram below – at least if we were to use MVVM for this project, which is not my preference.   With MVVM, our ViewModel[s] would be tightly coupled to our business logic layer and data transfer objects - we could not reuse them in any other module [without pulling in the kitchen sink].  In contrast the MVPVM ViewModel and View are completely decoupled and these components can be easily reused. Note on the right that my Gwn.Global.Presentation project is planning to include all reusable views and view models for user specific information [which makes sense as user information is reusable].  

Ironically, Microsoft’s ASP.NET MVC is the same pattern as MVPVM (presentation layer in figure 1), the irony being that ASP.NET MVC and SmallTalk MVC have nothing in common as the “controller” has a total different meaning, yet they adopted the newer MVP pattern using an old pattern name.   Martin Fowler says the following about this in his article on GUI architectures:

“Different people reading about MVC in different places take different ideas from it and describe these as 'MVC'. If this doesn't cause enough confusion you then get the effect of misunderstandings of MVC that develop through a system of Chinese whispers.”

The lesson you don’t want to miss here - a rose by any other name is still a rose.  Microsoft didn’t use MVVM, aka PresentationModel pattern, for its ASP.NET MVC framework - they used the MVP [VM] pattern.

MVPVM-005
Figure 1 draft project structure


MVPVM-002
Figure 2 mobile service layer

MVPVM-001
Figure 3 desktop/website

Adding Dependency Injection (Autofac) to ASP.NET MVC Core 2

Where the built-in Inversion Of Control (IOC), aka Dependency Injection (DI), container of ASP.NET MVC will meet most needs, sometimes we’ll want to utilize more advanced features of alternate IOC containers.  In the example below we are configuring for the use of Autofac (line 56), using a pattern consistent with existing code – an extension method.

AutoFac01

The extension method AddAutofacProvider code follows below:
AutoFac02

Note on line 13 above that we have an optional “builderCallback” action.  This provides the Startup ConfigureService method access to the builder instance created above on line 16.   Below on lines 56-60 is an example of how it might be used:
AutoFac03

Source code follows:

public static IServiceProvider AddAutofacProvider(
     this IServiceCollection services,
     Action<ContainerBuilder> builderCallback = null)
{
     // Instantiate the Autofac builder
     var builder = new ContainerBuilder();

    // If there is a callback use it for registrations
     builderCallback?.Invoke(builder);

    // Populate the Autofac container with services
     builder.Populate(services);

    // Create a new container with component registrations
     var container = builder.Build();
     var provider = new AutofacServiceProvider(container);

    // When application stops then dispose container
     container.Resolve<IApplicationLifetime>()
         .ApplicationStopped.Register(() => container.Dispose());

    // Return the provider
     return provider;
}






Configuring multiple environments with ASP.NET MVC Core 2

Source code available: HERE

With ASP.NET MVC Core 2, much of the configuration work is already done for us; it is configured for appsettings.{Environment}.json right out of the box.  Line 29 is all you’ll require for the Startup method.

config02

I added the following extension method (line 53 above) to simplify my ConfigureService code [being consistent with existing code]:

public static void AddAppSettings(this IServiceCollection services, IConfiguration configuration)
{
     var section = configuration.GetSection(nameof(AppSettings));
     services.Configure<AppSettings>(section);
}

My appsettings.development.json configuration file has a section “AppSettings” which contains one setting [as of this writing] it is “Environment”.   For consistency I created a AppSettings class that has a property name of Environment as required by the above “services.Configure<AppSettings>(section)” process; it will populate all AppSettings properties of the same name of the settings within the configuration file.

If you examine the Property page of your project you’ll find that the ASPNETCORE_ENVIRONMENT variable has already been set and defaults to “Development” – this will result in the appsettings.development.json file being used.   Since there are no other configuration files if you were to use any other name, e.g., “Production” it will default to the appsettings.json file.

config01

All that remains is to use constructor injection to retrieve the configuration settings.   With default usage [out-of-the-box] you can use the “IOptions<AppSettings> settings” parameter as shown on line 29 of the image below.  To retrieve an instance of AppSettings you’ll need to use the Value property of settings (reference line 33 below).   However, there is more information available [by default] that I want to have available to my application, so I also registered an “IAppSettings appSettings” (line 30) implementation that will provide all of the environment variables as well (see red arrow for AppSettings).  Note: I provide both methods for demonstration purposes only, I will only be using IAppSettings in my code.

config03

So if your only interested in the out-of-the-box usage, you are done here.  If you are interested in how to have the environment variables (in the case above 83 of them), please read on.

In the Startup class I not only modified ConfigureServices (as shown above) but also made an update to the Configure process as shown in bold below:

Config05

The UseAppsettings extension method (line 19 below) uses the service provider to obtain applicable services and then calls the AppSetting class Initialize method with an event argument that contains services.

Config04

The Initialize method above uses the event arguments (services) to retrieve and populate the ‘Values” property with the available settings.

Shift key stops working for Remote Desktop

Parallels is an excellent program for using an IMac for both Apple and PC development (more below), the only issue I encountered to date is that when I remote into my Slate [to develop in Visual Studio 2017] I lost the shift key functionality.
Adventures on the edge

Oddly the CAPS lock key worked but this was not a practical work-around.   I found that if I accessed the Control Center (#1-2 in image below), changed the Keyboard setting to “Optimize for games”, that the issue was resolved – the clue was the message below this dropdown setting.

Screen Shot 2017-12-08 at 7.55.36 AM

Where the IMac was purchased so I could develop in the Apple and Android environment (and my wife could use it for her business), I was pleasantly surprised to find out that if I went into “Full Screen” mode (#2 below) that I essentially had a full Windows experience with perks, e.g., I had downloaded an .rar file thinking I would have to find a utility to unpack it.  However, when I double-clicked the file it opened it while in my Windows environment using the Mac OS – very impressive.   “Coherence” is another impressive feature (#1 below), if you select this mode then your Windows applications will open under the Apple OS environment and I could access it via the Windows 10 environment (shared folder space).  With Coherence Windows and Apple applications open side-by-side as if the Windows application was native to it; it was odd seeing Visual Studio 2015 opening under the Mac OS.  

My personal preference is “Full Screen” mode as I can simply hold the control key and press the left and right arrows to switch between environments.  

Screen Shot 2017-12-09 at 5.45.54 AM