Rockford Lhotka

 Sunday, April 8, 2018
« The Decline of the Client OS | Main | WebAssembly talk at TCCC »


As you've probably noticed from my recent blogging, I'm very excited about the potential of WebAssembly, Blazor, and Ooui. A not-insignificant part of my enthusiasm is because the CSLA .NET value proposition is best when a true smart client is involved, and these technologies offer a compelling story about having rich smart client code running on Windows, Mac, Linux, and every other platform via the browser.

This weekend I decided to see if I could get CSLA running in Blazor. I'm pleased to say that the experiment has been a success!

You can see my log of experiences and how to get the code working via this GitHub issue:


At first glance it would appear that CSLA should already "just work" because you can reference a netstandard 2.0 assembly from Blazor, and the CSLA-Core-NS NuGet package is netstandard 2.0. However, it is important to remember that Blazor is experimental, and it is running on an experimental implementation of mono for wasm. So not everything quite works as one might hope. In particular, I ran into some issues:

  1. System.Linq.Expressions is unavailable in Blazor, which is how CSLA (and Newtonsoft.Json) avoid use of reflection in many cases (
  2. The DataContractSerializer doesn't work "out of the box" in Blazor (
  3. The Blazor solution template for a .NET Core host with Blazor client doesn't work if you reference one version of Csla.dll on the server, and a different version of Csla.dll on the client - so you have to use the same Csla.dll in both projects (
  4. The HttpClient type isn't fully implemented in mono-wasm, and it only supports passing string data, not a byte array
  5. You can't just create an instance of HttpClient, you need to use the instance provided via injection into each Blazor page

To address these issues I've created a new Csla.Wasm project that builds Csla.dll specifically to work in Blazor.

Issue 1 wasn't so bad, because CSLA used to use reflection on some platforms where System.Linq.Expressions wasn't available. I was able to use compiler directives to use that older code for Csla.Wasm, thus eliminating any use of Linq. There's a performance hit of course, but the upside is that things work at all!

Issue 2 was a bit more complex. It turns out there is a workaround to get the DCS working in Blazor (see issue 511), but before learning about that I used Newtonsoft.Json as a workaround. Fortunately this only impacts the MobileList type in CSLA.

Now keep in mind that Newtonsoft.Json doesn't universally work in Blazor either, because when it serializes complex types it also uses System.Linq.Expressions and thus fails. But it is capable of serializing primitive types such as a List<string>, and that's exactly the behavior I required.

Issue 3 is kind of a PITA, but for an experiment I'm ok with referencing the wasm implementation of Csla.dll on the server. Sure, it uses reflection instead of Linq, but this is an experiment and I'll live with a small performance hit. Remember that the wasm version of Csla.dll targets netstandard 2.0, so it can run nearly anywhere - just with the minor changes needed to make it work on mono-wasm.

Issue 4 required tweaking the data portal slightly. Well, the right answer is to create a new proxy/host channel for the data portal, but for this experiment I directly tweaked the HttpProxy type in CSLA - and that'll need to be corrected at some point. Really no change to the actual data portal should be required at all.

Issue 5 required tweaking the CSLA HttpProxy type to make it possible for the UI code to provide the data portal with an instance of the HttpClient object to use. This isn't a bad change overall, because I could see how this would be useful in other scenarios as well.

The BlazorExample project

The end result is a working Blazor sample, and you can see the code here:

This solution is mostly the Microsoft template.

  • BlazorExample.Client is the Blazor client app that runs in the browser
  • BlazorExample.Server is an ASP.NET Core app running on the server, from which the client app is deployed, and it also hosts the CSLA data portal endpoint
  • BlazorExample.Shared is a netstandard 2.0 class library referenced by both client and server, so any code here is available to both

Code shared by client and server

In BlazorExample.Shared you'll find a Person class - just a simple CSLA business domain class:

using System;
using System.Collections.Generic;
using System.Text;
using Csla;

namespace BlazorExample.Shared
  public class Person : BusinessBase<Person>
    public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
    public string Name
      get { return GetProperty(NameProperty); }
      set { SetProperty(NameProperty, value); }

    private static int _count;

    private void DataPortal_Fetch(string name)
      using (BypassPropertyChecks)
        Name = name + _count.ToString();

This type is available to the client and server, enabling the normal CSLA mobile object behaviors via the data portal. Anyone using CSLA over the years should see how this is familiar and makes sense.

Also notice that there's nothing unique about this code, this is exactly what you'd write for Windows Forms, ASP.NET, Xamarin, WPF, UWP, etc. One of the key benefits of CSLA - reuse your business classes across every platform where you can run .NET code.

The Blazor client app

In the client project there's a Program.cs file with the app's startup code. Here's where I configure the data portal and ensure there's a serializable principal object available:

Csla.DataPortal.ProxyTypeName =
Csla.DataPortalClient.HttpProxy.DefaultUrl = 
Csla.ApplicationContext.User = 
  new Csla.Security.UnauthenticatedPrincipal();

This is standard CSLA initialization code that you'll find in nearly any modern app. Same as WPF, UWP, Xamarin, etc.

I chose to do my UI experiments in the Pages/Counter.cshtml page.

The real highlight here, from a CSLA perspective, is the LoadPerson method; a handler for the "Load person" button:

async void LoadPerson()
    // Provide injected HttpClient to data portal proxy
    // Get person object from server
    person = await Csla.DataPortal.FetchAsync<BlazorExample.Shared.Person>("Fred");
    catch (Exception ex)
    errorText = ex.Message + ":: " + ex.ToString();

The unique thing here is where the SetHttpClient method is called to provide the data portal proxy with access to the HttpClient object injected at the top of the page:

@inject HttpClient Http

This particular HttpClient instance has been initialized by Blazor, so it has all the correct settings to talk easily to the deployment web server, which is also where I hosted the data portal endpoint.

The page also makes use of Blazor data binding. In particular, there's a person field available to the Razor code:

BlazorExample.Shared.Person person = new BlazorExample.Shared.Person();

And then in the Razor "html" this is used to display the business object's Name property:

<p>Name: @person.Name</p>

Because the LoadPerson method is async, it is necessary to tell Blazor's data binding to refresh the UI when the data has been retrieved. That call to StateHasChanged at the bottom of the method is what triggers the data binding UI refresh.

The ASP.NET Core web/app server

The server project has a couple unique things.

I had to work around the fact that a byte array can't be passed over the network from Blazor. So there's a modification to the CSLA HttpProxy class (client-side) to pass base64 encoded data to/from the server. For example:

//httpRequest.Content = new ByteArrayContent(serialized);
httpRequest.Content = new StringContent(System.Convert.ToBase64String(serialized));

Then in the server project there's a custom HttpPortalController class, copied from CSLA and also tweaked to work with base64 encoded data. For example:

string requestString;
using (var reader = new StreamReader(requestStream))
  requestString = await reader.ReadToEndAsync();
var requestArray = System.Convert.FromBase64String(requestString);
var requestBuffer = new MemoryStream(requestArray);

This controller is then exposed as an API endpoint via the DataPortalController class in the Controllers folder:

using Microsoft.AspNetCore.Mvc;

namespace BlazorExample.Server.Controllers
  public class DataPortalController : Csla.Server.Hosts.HttpPortalController

This is no different from hosting the data portal in ASP.NET Core (or ASP.NET MVC) in any other setting - except that it is using that custom controller base class that works against base64 strings instead of byte arrays like normal.

Because the BlazorExample.Shared assembly is referenced by the server project, the data portal automatically has access to the same Person type that's being used by the client, so again, the normal CSLA mobile object concept just works as expected.


I estimate I spent around 20 hours fighting through the various issues listed in this blog post. As per normal, most of the solutions weren't that hard in the end, but isolating the problems, researching possible solutions, testing the various solutions, and settling on the answer - that takes time and persistence.

Also - the support from the Blazor community on gitter is really great! And the team itself via GitHub - also really great!

One comment on this - there's no debugger support in Blazor right now, hence my tweet in the middle of my work:

That did make things a lot more tedious than normal modern development. It was like a throwback to 1990 or something!

The end result though, totally worth the effort! It is so cool to see normal CSLA code running in Blazor, data bound to a UI, and interacting with an app server via the data portal!