Skip to content

Repository files navigation

BlazorCausalityDemo

A demo from 2022 that sends LINQ queries from a client to a server over HTTP. You write a normal-looking fluent query on the client (Where, OrderBy, Skip, Take), the expression trees get serialized to bytes, posted to a generic API controller, rebuilt into an IQueryable<T> on the server, and run against EF Core + SQLite. Two different clients — a Blazor WebAssembly app and a plain console app — talk to the same backend with the same query code. It was written to play with the idea, not to ship.

What it demonstrates

The core trick is moving a LINQ query across the wire instead of building a custom endpoint per query shape.

  • A fluent builder, Linq<T> (BlazorCausality/Linq.cs), collects calls like .Where(...), .OrderBy(...), .ThenBy(...), .Skip(n), .Take(n), .Distinct(), and .Include(...) into an ordered List<Query>.
  • Each predicate is a real Expression<Func<T, bool>> (or Func<T, object>), serialized with Serialize.Linq over a BinarySerializer. The list is then JSON-serialized and POSTed to <entity>/get.
  • On the server, GenericController<T, C> (BlazorCausalityServer/GenericController.cs) deserializes the query list back into expression trees, replays them onto the entity's IQueryable in order via ConcatAndBuildQuery, and returns the result. It logs the SQL EF Core produced with queryable.ToQueryString() so you can see what actually hit the database.
  • The same MessageBroker : Linq<Message> type runs from both the Blazor client and the console app, so the query-building code is shared, not duplicated per host.

Honest about scope: GetById, Insert, Update, and Delete exist on the client repository and controller, the query side only supports the operators listed above, and there's a large block of commented-out experiments (Join, SelectMany, Select, string-based OrderBy) left in Linq.cs showing where the author was poking. Error handling mostly swallows exceptions and returns null or an empty list — fine for a playground, not for production.

Tech stack

  • .NET 6 (net6.0) across all six projects
  • Blazor WebAssembly (hosted model) for the web client
  • ASP.NET Core for the server host
  • Entity Framework Core 6 with the SQLite provider
  • Serialize.Linq 2.0.0 for expression-tree serialization
  • Newtonsoft.Json 13 for the query envelope
  • Serilog for server-side logging of the generated SQL

Note: the EF Core and ASP.NET Core WebAssembly packages are pinned to .NET 6 rc.1 preview versions (e.g. 6.0.0-rc.1.21452.10), which is what dates this repo. Restoring may need those preview packages available.

Project structure

Project What it is
BlazorCausality The library. Linq<T> builder, ClientRepository<T>, ServerRepository<T, TDataContext>, the Query/LinqType envelope, expression serialization extensions, EntityBase.
BlazorCausalityServer Server-side query rebuilding: GenericController<T, C> and QueryExpression<T>.
Shared (blazor.Shared) The shared Message entity (Id, UpdatedDate from EntityBase, plus Subject and Body).
Client (blazor.Client) Blazor WebAssembly app that lists messages.
Server (blazor.Server) ASP.NET Core host: serves the Blazor app, wires ApplicationDbContext to SQLite, registers the Message controller.
blazor.Console Console app that runs the same Where(...).OrderBy(...).ToListAsync() against the running server and prints the rows.

The SQLite file (Server/sqlite.db) and the EF migration for the Message table are committed, so the data is there on clone.

Getting started

You need the .NET 6 SDK.

In Visual Studio (the path the original README describes):

  1. Open BlazorCausality.sln.
  2. Set multiple startup projects: blazor.Server first, then blazor.Console.
  3. Confirm the server runs on https://localhost:7199. If it picks a different port, update the base address in blazor.Console/Program.cs (line 10) to match.
  4. Run without debugging. The Blazor app and the console app both come up against the same backend and the same local SQLite database.

From the CLI:

# build everything
dotnet build BlazorCausality.sln

# terminal 1 — start the server (serves the Blazor client too)
dotnet run --project Server/blazor.Server.csproj

# terminal 2 — once the server is on https://localhost:7199, run the console client
dotnet run --project blazor.Console/blazor.Console.csproj

The console app prints each Message it gets back; the Blazor client lists them at /. If the server lands on a port other than 7199, change the BaseAddress in blazor.Console/Program.cs before running the console app.

Status

A 2022 proof-of-concept, last touched April 2022. The library carries a 0.1.4-beta version and the preview-SDK pins were never updated. It works for the message query path it demos; the commented-out Join/SelectMany work was never finished. Treat it as an experiment in serializing LINQ across the wire, not a maintained library.

Author

Johan Olofsson, Noisy Cricket AB (noisycricket.se) johan.olofsson@noisycricket.se

The open-iconic font/icons bundled under Client/wwwroot/css/open-iconic/ ship under their own font and icon licenses (see the FONT-LICENSE and ICON-LICENSE files there).

About

Demo from 2022: a fluent LINQ builder serializes Where/OrderBy/Skip/Take expression trees, posts them to a generic ASP.NET Core controller, and rebuilds the query against EF Core + SQLite. Same query code runs from Blazor WebAssembly and a console app.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages