Be better WPF / MvvmLight developer in 2018

It is 2018, the time of .NET Core, x-plat, clouds, microservices, blockchain and shine of JavaScript. But, there are guys, like me, who still maintain and sometimes develop classic  .NET desktop applications for Windows.

I am not a WPF expert, but I spent a couple of days reviewing, testing and fixing one of our desktop apps and I definitely learned a couple of new tips & tricks that worth to share with other non-experts.

Part #1: General Tips

Tip #1.1: Choose right library/framework

It happened that we use MvvmLight. The library is lightweight and already exists for almost 10 years, MVVM pattern is well-known and lets us keep solution code reasonably well-structured.

But this is definitely not the only choice, there are many other different-purpose libraries and frameworks that may suit you better, especially if you do green-field development. So choose carefully:

Tip #1.2: Distribute using Squirrel.Windows

Installers always were hard, the seamless auto-update process is even harder. But, today, we have the solution that works for simple user-oriented applications that don’t do crazy things during installation. This solution is Squirrel.Windows – an installation and update framework for Windows desktop apps, designed for C# apps.

It’s definitely worth to learn it once and use it for all apps that you develop.

Tip #1.3: Think about monitoring

Aggregated analytics from user’s machine is priceless for successful apps. There are plenty amount of data that can help you deliver better apps:

  1. Crash reports
  2. Application version distribution
  3. User’s count / Active user
  4. Performance / Integrations tracking
  5. Custom events / Logs

It is not always possible to collect all kinds of data from user’s machine, but do it if you can. There are a couple of services that may help you, like Application Insights, HockeyApp and others.

Tip #1.4: Use the full power of IDE

Learn tools that MS baked for you and use them

Tip #1.5: Debug Data Binding Issues

When data bindings do not play nice you have a possibility to debug. It is not super intuitive, but there are ways to step into the binding process to better figure out what is actually going on. Check this nice article from Mike Woelmer – How To Debug Data Binding Issues in WPF 

Part #2: MVVM Light – Code Tips

C# quickly evolves over time, more and more features become available to us. It is not always obvious how to use new async code with an old API.

Tip #2.1: “New” INotifyPropertyChanged syntax

I think almost any WPF developer knows how to implement INotifyPropertyChanged interface

public class MyViewModel : INotifyPropertyChanged
{
    private string _isBusy;
    public event PropertyChangedEventHandler PropertyChanged;

    public MyViewModel() {}

    public string IsBusy
    {
        get { return _isBusy; }
        set
        {
            _isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged == null)
            return;
        PropertyChanged(this,
            new PropertyChangedEventArgs(name))
    }
}

Using MVVM Light you can do way shorter (such syntax probably exists for a while, but I discovered it only recently)

public class MyViewModel : ViewModelBase
{
    public MyViewModel() {}

    private string _isBusy;
    public string IsBusy
    {
        get => _isBusy;
        set { Set(() => IsBusy, ref _isBusy, value) }
    }
}

All property change events will happen under the hood of Set method. Also, Set method returns true when the value changed so you can use it to do additional actions on property change.

private string _isBusy;
public string IsBusy
{
    get => _isBusy;
    set {
        if (Set(() => IsBusy, ref _isBusy, value)) {
        // Do whatever you need on update
        }
    }
}

Update from Chris Jobson:

There are overloads that allow us to omit first argument – propertyExpression. In this case [CallerMemberName] will be used as the property name, so the code will be even shorter. Not bad for 2018 =)

private string _isBusy;
public string IsBusy
{
    get => _isBusy;
    set => Set(ref _isBusy, value);
}

Tip #2.2: Async to Action glue

C# async was designed to be better compatible with old APIs and consume Action or delegate. Also, it is one of the reasons why async void exists in the language, but we should always use async Task in our own code.

Two following casts are valid

Action task = async () => await Task.Yield();
Func task2 = async () => await Task.Yield();

Read “Do async lambdas return Tasks?” to better understand what’s actually going on here. It means that you can pass your async method as Action to RelayCommand.

new RelayCommand(async() => await Download());

TBH, you should use it like this (explanation in the next tip)

new RelayCommand(async() => await Download(), keepTargetAlive:true);

Tip #2.3: Do not use lambdas with RelayCommand

Lambdas as a parameter for RelayCommand is a bad idea unless you know what can go wrong and use the latest version of MvvmLight.

Actually, I have spent almost 2 days of my life to figure out why at some point of time several buttons in our application stopped working, even though all commands defined in the ViewModel are read-only and assigned once in the constructor.

We had simple commands that do some trivial actions on click, so the developer decided to use lambda in command declaration to save space and simplify the code.

new RelayCommand(() => IsBusy = true);

The code looks simple and correct, but RelayCommand under the hood stores only weak reference to the delegate and any GC cycle can recycle local lambda function. So at some point in time (after next cycle of GC) RelayCommand may not find delegate to call and nothing will happen after the click. For a deeper analysis of this behavior, you can read “RelayCommands and WeakFuncs“.

At the time of writing this post, the issues in MvvmLight library were fixed (Using RelayCommand and Messenger (and WeakAction) with closures) and released in version 5.4.1. But fix does not apply by default.

If you really want to use lambdas with RelayCommandMessenger you should manually set keepTargetAlive:true (false by default), but probably better do not use them at all.

new RelayCommand(() => IsBusy = true, keepTargetAlive:true);

P.S. Worth to mention that Laurent Bugnion has the course on Pluralsight “MVVM Light Toolkit Fundamentals” that provides detailed MVVM Light overview.

F# Weekly #15, 2018 – Virtual fsharpConf 2018, April 16

 

Welcome to F# Weekly,

A roundup of F# content from this past week:

News

Videos & Slides

Blogs

F# vNext

Open source projects

New Releases

That’s all for now. Have a great week.

Previous F# Weekly edition – #14, 2018Subscribe

IIS hosted products (Office Online Server) monitoring with Application Insights Status Monitor

There are some cases when you host and/or maintain 3rd-party .NET products in IIS and logs are not enough to understand the importance of some issues and find root causes. You may need the high-level view of what’s actually going on live.

Fortunately, Microsoft has a tool called Application Insights Status Monitor that can help you to instrument your IIS site with required configs to start collecting telemetry data into Application Insights.

There are blog posts like “Configure an IIS Server To Use Application Insight” that already provide step by step guide on how to use the tool.

In this post, I want to go one step further and share some tips on how to use it for Microsoft products. So here you can find extra steps which you may need during setup on Office Online Server, but I guess that you can do the same with on-premise SharePoint farm as well.

Configure Telemetry for Office Online Server

  1. Create a new instance of Application Insights
  2. Install Application Insight Status Monitor on machines with Office Online Server. You can do it using the direct link http://go.microsoft.com/fwlink/?LinkID=506648 that will run installation using Web Platform Installer.
  3. Download update (the latest SDK version from NuGet). Click “Update is available” and then “Install Update”.EPAM_Laptop.png
    You may see an error message that app cannot download new SDK from NuGet
    EPAM_Laptop.png
    This can mean that IE Enhanced Security Configuration is enabled on your server, in this case, you need to temporarily turn it off:

    1. Open Server Manager
    2. Go to Local Server, find “IE Enhanced Security Configuration” and turn it off.
      Do not forget to turn it on again when you finish this guide!EPAM_Laptop.png
  4. Sign in using your Azure account
    1. Your sign in flow may end with error “Authentication failed: service_returned_error: Service returned error. Check InnerException for more details
      EPAM_Laptop.png
    2. Go to Event Viewer\Windows Logs\System. If you see Errors from Schannel with a message like “A fatal error occurred while creating an SSL client credential. The internal error state is 10013.” then it is System-wide crypto issue and you need to allow “Use FIPS compliant algorithms for encryption, hashing, and signing” and try to sign in again.
  5. Configure each IIS application to send telemetry to Application Insights resource created in step 1.
    EPAM_Laptop.png
  6. Restart IIS from the Status Monitor app to start collecting telemetry data.
  7. Wait for some time to collect enough data to analyze (for example one day).
  8. After that, you can start digging deeper into collected stats to better understand what’s actually going on.
    EPAM_Laptop.png
  9. Turn on IE Enhanced Security Configuration.

Performance Counters Note: Actually Application Insights Status Monitor does two simple things: updates web.config to incorporate Application Insights and puts ApplicationInsights.config beside with configuration. By default, it is configured to collect data from performance counters, but it may not work if your Application Pool is running under an account that does not have permissions to access performance counters. Note, that in this case, you have to add App Pool account to Performance Monitor Users group. Read more.

F# Weekly #14, 2018 – Microsoft uses​ SAFE as a form of validation for .Net core

Welcome to F# Weekly,

A roundup of F# content from this past week:

News

F# Exchange

Videos & Slides

Blogs

F# vNext

Open source projects

  • CNTK.FSharp – F# utilities to make the CNTK .NET API pleasant to use from the F# scripting environment
  • flatware – Type-safe F# state management (like Elm and Redux) for Blazor
  • safe-dojo – An introductory dojo to learn how to develop full stack web applications in F#
  • altcover – Instrumenting coverage tool for .net/.net core and Mono, emitting NCover or OpenCover
  • panesofglass/trail – ASP.NET Blazor rendering with F#
  • JetBrains/fsharp-support – F# support in JetBrains Rider

New Releases

That’s all for now. Have a great week.

Previous F# Weekly edition – #13, 2018Subscribe