Aside

Blazor Server Tip: Sometimes you need Task.Delay(1)

I recently encountered an issue with server-side Blazor in which the UI didn’t refresh after calling StateHasChanged. The UI refreshed just fine until I added about 30k more records to a database table, which caused a query to take a bit longer to run. I filed an issue here.

I debugged through the issue by trying different things like using an in-memory data store, re-checking against a smaller data set, and wrapping StateHasChanged to make sure it was actually called. Everything was working as expected with the in-memory store and smaller data set, and StateHasChanged was always called. However, with the larger data set, the components’ lifecycle methods were not called.

I finally stumbled upon a solution using an old JavaScript trick: adding await Task.Delay(1); This magically worked. If you run into something similar, you may try await Task.Delay(1); and see whether that resolves the issue.

Advertisement

Yet Another F# Web Framework

Update Jan 1, 2019

I spent some time splitting the projects and updating to ASP.NET Core 3.0 alpha (preview targets netcoreapp3.0 only). The Endpoint Routing feature is really, really nice. You can see the updated version here (diff).

Original Post

While evaluating the state of F# web frameworks over the holidays, I managed to create yet another lightweight framework prototype. You’re welcome. The prototype is based on ASP.NET Core Routing and some posts by Filip Wojcieszyn, specifically Building microservices with ASP.NET Core (without MVC) and Running ASP.NET Core content negotiation by hand. The prototype currently consists of a ContentNegotiation module and a Builder module containing a RouterBuilder and a ResourceBuilder, where the two builder types are computation expressions using CustomOperationAttributes.

let helloName =
    resource app.ApplicationServices "hello/{name}" {
        name "Hello Name"

        get (fun ctx ->
            let name = ctx.GetRouteValue("name") |> string
            ctx.Response.WriteAsync(sprintf "Hi, %s!" name))

        put (fun ctx ->
            let name = ctx.GetRouteValue("name") |> string
            ContentNegotiation.negotiate 201 name ctx)
    }
Continue reading

Demand Driven Architecture or REST or Linked Data?

I recently listened to David Nolen‘s talk from QCon London conference from back in July called Demand Driven Architecture. Before continuing, you should have a listen.

Ready?

I really like a lot of things Mr. Nolen has done and really enjoy most of his talks and posts. I was less enthused with this one. I think my main hang up was his mis-representation of REST and resources. I get the feeling he equates resources with data stores. If you watched the video and then skimmed that Wikipedia page, you will quickly see that the notion of “joining” two resources is nonsensical. I think Mr. Nolen is really referring to that “pragmatic” definition that means POX + HTTP methods, which really would correlate well to data stores.

Continue reading

Working with Non-Compliant OWIN Middleware

Microsoft.Owin, a.k.a. Katana, provides a number of very useful abstractions for working with OWIN. These types are optional but greatly ease the construction of applications and middleware, especially security middleware. The Katana team did a great job of ensuring their implementations work well with Microsoft.Owin as well as the standard OWIN MidFunc described below. However, not all third-party middleware implementations followed the conventions set forth in the Katana team’s implementations. To be fair, OWIN only standardized the middleware signature earlier this year, and the spec is still a work in progress.

At some point in the last year, I discovered the HttpMessageHandlerAdapter was not, in fact, OWIN compliant. I learned from the Web API team they would not be able to fix the problem without introducing breaking changes, so I came up with an adapter that should work with most implementations based on OwinMiddleware that didn’t expose the OWIN MidFunc.

The solution is rather simple, and the Katana source code provides one of the necessary pieces in its AppFuncTransition class. The adapter wraps the OwinMiddleware-based implementation and exposes the OWIN MidFunc signature. After creating the adapter specifically for HttpMessageHandlerAdapter, I created a generic version I think should work for any OwinMiddleware. (Examples in both C# and F#.)


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AppFunc = Func<IDictionary<string, obj>, Task>;
using MidFunc = Func<AppFunc, AppFunc>;
public class MidFuncType
{
private readonly AppFunc next;
public MidFuncType(AppFunc next)
{
this.next = next;
}
public Task Invoke(IDictionary<string, obj> environment)
{
// invoke the middleware, call `next`, etc.
// return the `Task`
return Task.FromResult<obj>(null) :> Task
}
}


open System
open System.Collections.Generic
open System.Threading.Tasks
type AppFunc = Func<IDictionary<string, obj>, Task>
type MidFunc = Func<AppFunc, AppFunc>
type MidFuncType(next: AppFunc) =
// set up the middleware
member this.Invoke(environment: IDictionary<string, obj>) : Task =
// invoke the middleware, call `next`, etc.
// return the `Task`
Task.FromResult<obj>(null) :> Task


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin;
using System.Web.Http.Owin;
using AppFunc = Func<IDictionary<string, obj>, Task>
/// See https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin/Infrastructure/AppFuncTransition.cs
internal sealed class AppFuncTransition : OwinMiddleware
: base(null)
{
private readonly AppFunc next;
public AppFuncTransition(next: AppFunc)
{
this.next = next;
}
public Task Invoke(IOwinContext context)
{
// TODO: check for null
return this.next(context.Environment)
}
}
/// Explicit wrapper for HttpMessageHandlerAdapter
public class OwinMessageHandlerMiddleware
{
private readonly OwinMiddleware next;
OwinMessageHandlerMiddleware(AppFunc next, HttpMessageHandlerAdapterOptions /* I think this is the right name */ options)
{
var nextKatana = new AppFuncTransition(next);
this.next = new HttpMessageHandlerAdapter(nextKatana, options);
}
public Task Invoke(IDictionary<string, obj> environment)
{
// TODO: check for null
var context = new OwinContext(environment);
return next(context);
}
}
// This can be made generic:
/// Generic OwinMiddleware adapter
public abstract class OwinMiddlewareAdapter
{
private readonly OwinMiddleware next;
protected OwinMiddlewareAdapter(AppFunc next, Func<OwinMiddleware, OwinMiddleware> factory)
{
var nextKatana = new AppFuncTransition(next);
this.next = factory(nextKatana);
}
public Task Invoke(IDictionary<string, obj> environment)
{
// TODO: check for null
var context = new OwinContext(environment)
return next(context)
}
}
/// HttpMessageHandlerAdapter using the Generic OwinMiddleware adapter
public class OwinMessageHandlerMiddlewareAdapter : OwinMiddlewareAdapter
{
public OwinMessageHandlerMiddlewareAdapter(AppFunc next, HttpMessageHandlerAdapterOptions /* I think this is the right name */ options)
: base(next, m => new HttpMessageHandlerAdapter(m, options))
{
}
}


open System
open System.Collections.Generic
open System.Threading.Tasks
open Microsoft.Owin
open System.Web.Http.Owin
type AppFunc = Func<IDictionary<string, obj>, Task>
/// See https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin/Infrastructure/AppFuncTransition.cs
[<Sealed>]
type AppFuncTransition(next: AppFunc) =
inherit OwinMiddleware(null)
default x.Invoke(context: IOwinContext) =
// TODO: check for null
next.Invoke(context.Environment)
/// Explicit wrapper for HttpMessageHandlerAdapter
type OwinMessageHandlerMiddleware(next: AppFunc, options) =
let nextKatana = AppFuncTransition(next) :> OwinMiddleware
let webApiKatana = new HttpMessageHandlerAdapter(nextKatana, options)
member x.Invoke(environment: IDictionary<string, obj>) =
// TODO: check for null
let context = new OwinContext(environment)
webApiKatana.Invoke(context)
// This can be made generic:
/// Generic OwinMiddleware adapter
type OwinMiddlewareAdapter(next: AppFunc, factory: Func<OwinMiddleware, OwinMiddleware>) =
let nextKatana = AppFuncTransition(next) :> OwinMiddleware
let middlewareKatana = factory.Invoke(nextKatana)
member x.Invoke(environment: IDictionary<string, obj>) =
// TODO: check for null
let context = new OwinContext(environment)
middlewareKatana.Invoke(context)
/// HttpMessageHandlerAdapter using the Generic OwinMiddleware adapter
type OwinMessageHandlerMiddlewareAdapter(next: AppFunc, options) =
inherit OwinMiddlewareAdapter(next, (fun m -> new HttpMessageHandlerAdapter(m, options) :> _))

I hope that helps someone else. If there’s interest, I can package this up and place it on NuGet, though it seems a lot of effort for something so small. The source code above is released under the Apache 2 license, in keeping with the use of AppFuncTransition used above from the Katana source.

Bundling and Minification with Web Essentials

Pta.Build.WebEssentialsBundleTask A few months ago, the Tachyus web application used a C# + F# web application approach to separate the front-end HTML, CSS, and JavaScript from the back-end F# ASP.NET Web API application. With this configuration, we introduced Web Essentials to bundle and minify our CSS and JavaScript at build time within Visual Studio. To simplify deployments and better group related and shared code, we decided to merge the back-end with another Web API application, which used the F# MVC 5 project template. We originally tried using CORS, which worked great in almost every environment. Unfortunately, the one environment in which we ran into trouble was our staging/production environment. Since we are building an internal-only API, we haven’t spent the extra effort to make our APIs evolvable; therefore, we decided to just merge all three projects together into the F# web project. This worked rather well, except for Web Essentials. We abandoned Web Essentials, as well as any form of bundling or minification at that time.

Fast forward to last week: we again split the front-end application out into a separate, C# project. We did this for several reasons:

  • We ran into trouble trying to remote debug the F# web project
  • The project had grown to the point that it was quite large, and it made sense to separate the two for maintenance
  • It’s common even in other languages to separate the front-end into a separate folder or project as different teams are often responsible for the different apps, which is not quite our case but close
  • We wanted to clean up our Angular code so that we had less Angular spread throughout and more standard JavaScript; for this we wanted to use bundling again

I was able to add Web Essentials back into the solution since we were again using a C# project. However, this had its own challenges, specifically in the form of communication to the rest of the team that they would need to install Web Essentials in order for their updates to take effect.

Fortunately, my colleague Anton Tayanovskyy recently found and pointed me toward the WebEssentialsBundleTask, which is a MSBuild task that will run the Web Essentials transformations at runtime depending on the build configuration, i.e. Debug or Release. This tool provides explicit script references for Debug builds and a bundled (and minified, if desired) version for Release builds. It seems to only require the presence of a Web Essentials-style .bundle file to work, so I would expect this to work equally well with a F#-only solution, though I have yet to try that. The WebEssentialsBundleTask has its own issues, though. It will modify your index.html file whenever it runs, so you must make sure to revert changes you don’t want to keep. We rarely change our index.html file since nearly everything is built in the form of Angular directives or templates. Nevertheless, you should consider the cost to your own project.

You may wonder why we didn’t just build a simple FAKE task. After all, whitespace in JavaScript is relatively meaningless, so a very simple concat + remove could probably get the job done, especially since we use ; where applicable. I definitely considered this option, as well as creating new FAKE tasks built around a node.exe using tools like grunt.js or gulp.js. In the end, these all seemed like overkill with the availability of Web Essentials, at least until we had evaluated whether WE would work for our purposes. We are still evaluating. What are you using? Did you find this helpful?

F# Web Stack Group

I’ve recently seen an increase in the number of those interested in F# programming for web development. I don’t think this is a recent phenomenon; I just haven’t had the privilege of running into many of them previously. Nevertheless, we have decided to band together to provide a set of useful, well-designed libraries for web development in F#.

If you are interested in learning more, please join us in the F# Web Stack Google Group. I’ve added a list of current projects and efforts in the welcome message so that you can gain your bearings quickly. Current topics include merging various projects into a cohesive stack and planning one or more type providers to build out server and client boilerplate from API documentation.

Video

WebSharper UI Improvements

The WebSharper project has been making significant strides of late in the realm of building composable and reactive user interfaces, especially for the purpose of building SPA-style applications. You can find documentation and demos for WebSharper.UI.Next on its new site hosted on GitHub. Team members have also been blogging about how to build UIs with the new tools on the WebSharper blog.

Anton Tayanovskyy also joined Community for F# a month or so ago to describe the concepts behind the design of WebSharper.UI.Next and how it is different from some other popular approaches, including the virtual DOM approach used in Facebook’s React library. You can find the recording on YouTube.