Latest Posts

A Simple Orleans Implicit Stream Example

While exploring Microsoft Orleans for potential use in developing a CQRS & Event Sourced application, I was delighted to see Implicit Streams being supported as a method for propagating Events to Grains. Unfortunately, at the time of this writing, the documentation is a little lacking in how to properly setup Implicit Streaming. Fortunately, there are official samples that cover most use cases, including Implicit Streaming, but those require using Event Hubs, which is hardly a “download & run” scenario. As such, I have provided a completely barebones sample to demonstrate how Implicit Streaming is setup. https://github.com/jsedlak/orleans-samples/tree/main/Streaming/ImplicitStreams The solution contains three projects: A Shared Library containing all the common code, an Orleans Client, and an Orleans Host. Here are the key points to know. We create a few constants to ensure we’re always referencing the correct stream. In our Silo configuration, we’re going to add Memory Streams with our custom Provider Name, and inform the framework that this provider will be Implicit Only, allowing us to proceed without a PubSubStore. Our Producer Grain is going to create the Stream and register a Grain Timer to introduce stream data every N=1 seconds. It is also worth noting the sample uses 8.2.0, which utilizes the new RegisterGrainTimer method. We expose this as a Grain Method in the IProducerGrain interface to ensure the Client can control when stream data starts producing. On every tick of the timer, we simply increment a count and send it to the Stream using OnNextAsync. What is not clear

Read More

Building an Offline Indicator in Blazor

If you’re building a Progressive Web Application (PWA), chances are you’ll want to show the Online/Offline status of the browser to help keep the user informed. Fortunately, there is an incredibly simple Browser API for accessing this data! This article discusses how we’ll integrate the javascript API into a simple Blazor component. This article assumes basic knowledge of setting up a Blazor project and/or component library. The first step is to build out the javascript function that allows us to notify the Blazor/.NET side that the Online status has changed. Head over to the js interop file in your project, or make a new one. This function will take a special “.net reference” that allows us to invoke .NET methods from javascript (usually we go the other way!). We simply listen to the online and offline methods and notify the reference through a known interface (method). Now, on the Blazor side, we need an object that can both call this method and pass in a reference [to itself] to be notified of changes through the invokeMethodAsync callback. That means building a class that utilizes the IJSRuntime. If you wish to have this dependency injected, you can then add this to the client side’s service collection. And finally, we need to build the component that actually renders out some interesting HTML to look at! In many of my projects, I employ the use of Heroicons and Tailwind CSS – that will be no different here. The component simply uses a dependency

Read More

Method for Dependency Injected HttpClient Service Access

The inevitability of most Blazor applications is the use of HttpClient to reach out to API endpoints. Many times, these endpoints are contained within the solution, but they may be external as well. Without much effort, this necessity quickly turns into a rats nest of initialization code in razor code with hardcoded strings for each endpoint. The pattern I will describe in this post is designed to make this a simpler experience. For the purposes of this post, I’m going to use the Blazor WebAssembly template with ASP.NET Core hosting to keep client and server separate – mostly to demonstrate the capabilities in a cross assembly fashion. Hot Tip Just because the default templates define a “Shared” library and namespace, it can often make sense to trim out the “Shared” portion from the default namespace to simplify razor using statements. The first thing we need to do is define the functionality our service will support. This should match, at least partially, the methods defined by your API controllers. We’ll use the built in Weather Forecast as our example. Now that we have an interface defined, we will add it to the WeatherForecastController class definition. Other than updating the method to be async and return a Task, no other changes should be necessary since the interface matches the definition of the controller. Now, before we get to the magic – I’m going to define a helper interface. While this is not necessary to everyone’s use case, I found it useful to

Read More

Petl: Developer Friendly, Testable View Storage in Sitecore

As the timescale for Sitecore’s built-in indexing reached multitudes of hours rather than minutes, it was time to come up with a new solution. We still needed some of what SOLR was providing in terms of searching by term, but only for back office processes. For the storefront, we were using SOLR more as a view store than any sort of search index. Site search was being provided by a separate provider that utilized the indexing mechanism. That too, would need looking at. If you’d like to skip the reading and get to the code, you can view the project at https://github.com/jsedlak/petl Sitecore Indexing Shortcomings Going back to my first experiences with Sitecore (10+ years ago!), indexing wasn’t at the forefront of my mind. I knew it existed, but I was more interested in writing fancy XSLTs, and the systems we ran on were beefy enough to support it. As time went on and I was exposed to more voluminous websites with more consistently high traffic, indexing slowly became the only thing that mattered. For an e-Commerce site, having quick access to reliable product information is vital. Faster page loads with more precise pricing and inventory information means a higher purchase rate. It’s really as simple as that, at least from a backend developer’s perspective. But as your catalog grows, indexing runs into a serious problem. It has to run through every item in every language and decide what to do with it, based on your configuration. And while there

Read More