OdeToCode IC Logo

Beautiful Binary Literals

Wednesday, January 8, 2020 by K. Scott Allen

Finally! I've used binary literals in real code. This feature, and the digits separator have been good additions to the C# language.

public static byte[] BreakIntoTwos(byte value)
{
    var result = new byte[4];

    result[0] = (byte)((value & 0b1100_0000) >> 6);
    result[1] = (byte)((value & 0b0011_0000) >> 4);
    result[2] = (byte)((value & 0b0000_1100) >> 2);
    result[3] = (byte) (value & 0b0000_0011);

    return result;
}

Switch Expressions are the Best Feature of C# 8

Monday, January 6, 2020 by K. Scott Allen

I thought <Nullable>enable</Nullalble> would be the star of the C# 8 show by now, but in day to day work I'm finding that switch expressions are stealing the show.

Size = 1 + Operands.Size;
OpCode = Bits.BottomFive(memory.Bytes[0]);

Operation = OpCode switch
{
    0x01 => new Operation(nameof(JE), JE, hasBranch: true),
    0x0A => new Operation(nameof(TestAttr), TestAttr, hasBranch: true),
    0x0F => new Operation(nameof(LoadW), LoadW, hasStore: true),
    0x09 => new Operation(nameof(And), And, hasStore: true),
    0x10 => new Operation(nameof(LoadB), LoadB, hasStore: true),
    0x14 => new Operation(nameof(Add), Add, hasStore: true),
    0x0D => new Operation(nameof(StoreB), StoreB),
    _ => throw new InvalidOperationException($"Unknown OP2 opcode {OpCode:X}")
};

I was never a fan of switch statements, but switch expressions have the ability to reduce nasty, nested, cyclomatically complex code into a tabular, declarative display of elegant simplicity.

Another example:

var instruction = memory.Bytes[0] switch
{
    0xBE => DecodeExt(memory),
    var v when Bits.SevenSixSet(v) => DecodeVar(memory),
    var v when Bits.SevenSet(v) => DecodeShort(memory),
    _ => DecodeLong(memory)
};

Something to Know about gRPC in ASP.NET Core 3

Tuesday, October 22, 2019 by K. Scott Allen

gRPC is a framework you can use in ASP.NET Core 3 to build APIs. The gRPC framework offers both advantages and disadvantages compared to the HTTP based APIs we’ve always been able to build using ASP.NET Core controllers. But, there’s one important aspect of gRPC that is often overlooked in the wave of 3.0 evangelism you read in blogs, hear in podcasts, and see in videos and conferences:

gRPC services won't work in IIS or Azure App Services.

IIS and App Services constitute a non-trivial share of production environments for AspNet Core, so it is regrettable that some developers discover late in the development process that gRPC won’t work for them. Only recently has the documentation for gRPC started to include a warning message:

gRPC warning

What Doesn’t Work?

The warning itself is misleading. IIS and App Services have two different problems.

It’s true that IIS cannot current host a gRPC service because http.sys doesn’t support trailing headers. gRPC relies on trailing headers to communicate vital information, like call status. The first sign of trouble here appears when you scaffold a new gRPC service project using Visual Studio. AspNet Core projects typically include the option to develop using IIS Express, but this launch option is not present after running the gRPC scaffolding.

In Azure, Windows based App Services use IIS and have the same http.sys limitation. However, you can’t circumvent the problem by hosting in a Linux or using a custom container. The App Service front-end terminates incoming TLS connections before forwarding unencrypted messages to your App Service worker. Your gRPC service will refuse to communicate over http and return only HTTP 426 Upgrade Required errors.

Summary

There’s currently no timetable I can find for either IIS or App Services to make a workable environment for gRPC services. Fortunately, there are other options for hosting gRPC services in Azure and the cloud including using Kestrel directly in a virtual machine or in a Kubernetes cluster.

The bigger issue for me is the reoccurring problem where Microsoft messaging around new AspNet Core features doesn’t consider the realities of production. Another example of this problem was with the original .NET Core release. While Microsoft was promoting the record performance benchmarks of AspNet Core, all of us hosting AspNet Core on IIS were seeing performance numbers worse than MVC 5. The confusion took a long time to clear up.

UseNodeModules Updated for .NET Core 3

Monday, October 7, 2019 by K. Scott Allen

UseNodeModules is a NuGet package I put together a few years ago. The package gives you an easy way to install middleware for serving content directly from the node_modules folder in an ASP.NET Core project.

 public void Configure(IApplicationBuilder app)
{
    app.UseNodeModules(maxAge: TimeSpan.FromSeconds(600));
}

The idea is that during development you can use npm to manage all your client-side dependencies and you can use those dependencies immediately instead of setting up a process to copy files into the wwwroot folder. In production, you might use environment tag helpers to serve files you’ve bundled during a build, or to use minified files from a CDN. During development, however, you don’t have to wait for bundling, minification, and copying to occur.

Here's an example with Bootstrap 4. In development we'll serve directly from the node_modules folder. In any other environment we'll serve a minified file from a CDN, but with fallbacks to the node_modules folder in case the CDN is unavailable.

<environment include="Development">
    <link href="~/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
</environment>
<environment exclude="Development">
    <link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/4.3.1/css/bootstrap.min.css"
    asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
    asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
</environment>

Be aware that dotnet publish will not copy the node_modules folder to the published output directory. You can change this behavior by adding the following to the .csproj file.

<ItemGroup>
    <Content Include="node_modules\**" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>

A nice side benefit of the above code is how Visual Studio users will also see node_modules in the Solution Explorer view. Otherwise, the folder is hidden by Visual Studio, which I’ve never understood.

Thanks to Shawn Wildermuth for the help!

The Blazor Bet

Tuesday, September 24, 2019 by K. Scott Allen

Today's release of .NET Core 3 is significant. By supporting Windows desktop development and dropping support for the full .NET framework, v3 makes a statement - not only is .NET Core here to stay, but .NET Core is the future of .NET.

Included in all the fanfare is Microsoft's new web UI framework by the name of Blazor. Blazor gives us the ability to write interactive UIs using C# instead of JavaScript and it works using one of two different strategies. The first strategy compiles C# code into WebAssembly for execution directly in the browser. This WebAssembly strategy is still experimental and won't see a supported release until next year.

The second strategy sends client events to the server using SignalR. C# code executes on the server and produces UI diffs, which the framework sends back to the client over SignalR for merging into the DOM.

Server-side Blazor

Most people won't see much risk in moving to .NET Core these days. Blazor, on the other hand, doesn't have a clear path to success.

Out of the Frying Pan

Client-side development is a subjective experience. There are developers who embrace the organic JavaScript ecosystem. There are also developers who are desperate to see Blazor succeed because the messiness of working with disparate package managers, compilers, and frameworks du jour is raw and frustrating. These individuals don't necessarily dislike JavaScript, but they do feel vastly more comfortable and productive using a language like C# and tools designed to work seemlessly end to end.

These developers typically stick to building applications using server-rendered HTML because the environment is simple and productive. Yes, there is always a push to be more interactive, depending on the type of application being built, but sometimes a well-placed JS component will work well enough and avoid the complexities of building a full blown SPA.

For these teams that have avoided the Angulars, Reacts, and Vues – is now the time to jump into client UI using Blazor?

Typical Blazor App

And into the Fire

One of the first arguments against Blazor is the "look what happened to Silverlight" argument, a reference to Microsoft's last successful client UI framework. A framework Microsoft killed just as the framework was reaching peak popularity.

I personally don't consider what happened with Silverlight to have any impact on the decision to use Blazor, or not. I say this partly because Microsoft is a different company today compared to 10 years ago, but also because every Microsoft product and framework faces the same risk. Microsoft will always be inventing frameworks, then promoting and evangelizing those frameworks as the solution to all software problems. Microsoft will continue investing in those frameworks until one day, something better comes along, and suddenly, with no fanfare or formal announcement, you'll find the framework dead on the vine.

This isn't just Microsoft's history for decades, but a chronic condition of the software industry. Ask WCF customers.

The bigger risk, I think, is in the execution strategies. The WebAssembly approach, where code executes in the browser, is the solution we want to see working, but WASM is still in preview because of technical issues. When the WASM approach does arrive, we still need to evaluate how well the approach works. How much does the browser need to download? How good is DOM interop from C# code? How will the compiler work with all the evolving interfaces of the W3C? Will the development experience be as iterative as today's hot-reload experience? There's many questions to answer.

Blazor and WASM

With WebAssembly on hold, we are left with the server-side execution model. But, there's something about this model that doesn't pass a sniff test. We've been told over the years that stateful web applications are evil. We've been told over the years that the network is slow, unreliable, and not to be trusted. Suddenly, Blazor enters the room and talks about storing state on the server and running click events over the network. The mind explodes with questions. Does this even scale? Can it be trusted? What happens to my mobile users in a train tunnel?

Everything about this first version is wrapped in caution tape. Everyone wants to make a prototype to see how it works. Nobody is ready to bet the farm.

Consider Issue Number 12245

Remove stateful prerendering is an innocuous title, but the implications for Blazor are considerable.

To summarize the issue – each Blazor component requires some space on the server. If you request too many components, the server can run out of space. Thus, malicious users can leverage Blazor to DOS your servers.

Issue 12245 is the type of issue that comes to mind when "run client logic on the server" is listed as a Blazor feature. How can there not be issues with security and scale?

Like with many security problems, the solution is to eliminate a useful feature. Now, you can't use Blazor to render a component that depends on a piece of state or a parameter. The only state the component can use is state the component creates once the component connects to the server.

Unfortunately, the solution eliminates many component use cases. Let's say I don't want to build a SPA. I want to add interactivity to specific pages in an app. To do so, I'll create components that can render an account by ID, or show the score for games on a specific date. With stateful prerendering it was easy to pass an ID or a date to a component and let the component go out and fetch whatever data it needs.

No stateful prerendering means there is no direct mechanism for passing parameters to a component. Components will need to dig parameters out of a URL, or use JSInterop to fetch parameters from state embedded in a page. Although both are possible, it does make some component scenarios impossible, and almost all scenarios become a bit more hacky.

Summary

In the end, I believe WebAssembly is the model we want to use with Blazor. I'm curious to see if the server-side model, with it's inherent limitations, will continue to live once WebAssembly arrives. The server model will probably be easier for developers to use, but we can already see how limitations will hinder widespread adoption.

New Pluralsight Course – ASP.NET MVC 5 Fundamentals

Wednesday, September 18, 2019 by K. Scott Allen

Yes, ASP.NET MVC 5 Fundamentals is a new course, made from scratch, and made with care.

I’ve been asked why I’m taking the time to make courses on frameworks that are old and out of fashion. The answer is because an extraordinary number of extraordinary people work with this legacy framework, and my existing MVC 5 course was out of date. As the author of several legacy-but-still-revenue-generating web forms applications, I have a soft spot for developers who aren’t working with the latest and greatest technologies. This new MVC 5 course is for those developers who quietly keep the lights on in the world.

MVC 5 Fundamentals

.NET Core Opinion 14 - Razor Pages for HTML, Controllers for APIs

Thursday, September 12, 2019 by K. Scott Allen

.NET Core opinions are returning from a summer holiday in time to brave the melancholia of autumn.

ASP.NET Core 2.0 introduced Razor Pages, which I believe are superior to the MVC framework when building HTML applications with .NET Core.

Razor Pages encourage a separation of concerns in presentation layer logic, just as the MVC framework does. Razor pages also follow patterns like dependency injection that promote flexibility and testability. But, Razor Pages also offer clear advantages over MVC when generating HTML and processing forms on the server.

Pages Bring Focus

Razor Pages encourage developers to remain constrained in the number of features they add to a class. With pages, you typically pick a specific feature to implement using only GET and POST methods, while controllers can grow to implement dozens of different actions.

Pages versus Controllers

It was easy to see the overstuffed controller phenomenon when using the ASP.NET Identity framework. The Razor Pages version of ASP.NET Identity (shown below on the left) makes it easy to find specific features because the pages are granular. The controller version uses only two controllers with dozens of assorted actions inside. It’s worth noting that the ASP.NET Identity project now supports only Razor Pages when scaffolding a UI.

Imagine trying to find the functionality to change a password in the application. With Razor Pages it is easy to spot the page, while the controller approach hides the feature inside a mega-controller with views and models scattered across other directories.

Pages Organize Features

Speaking of feature organization, I’ve always been a fan of feature folders with the MVC framework. The MVC design pattern wants us to separate concerns using controllers, views, and models. But, nothing in the MVC framework says the models, views, and controllers need to be physically separated into distinct files and spread across separate directories. One of the more frustrating aspects of working with MVC, other than HTML helpers, was trying to track down all the files I need to open when working on a specific feature.

Razor pages maintain a separation of concerns without spraying code across the file system. The page code functions like a controller while the page view contains the presentation logic. You’ll find the code file and the view file nested together. Models and view models can live anywhere but are typically exposed as direct properties of the page, so all the pieces are easy to find.

public class DetailModel : PageModel
{
    private readonly LeagueData leagueData;

    public int SwanCount = 59;
    public Season Season { get; set; } = new Season();

    public DetailModel(LeagueData leagueData)
    {
        this.leagueData = leagueData;
    }

    public void OnGet(int id)
    {
        var query = new SeasonDetailQuery(id);
        Season = leagueData.Execute(query);
    }
}

Pages Build Better URLs

Anecdotal evidence tells me that applications built with Razor pages have better URL structures than apps with controllers. Controller apps tend to overuse the default routing template, which leads to a flat URL structure and lots of controller actions taking an ID parameter. Razor pages, on the other hand, tend to promote the organization of related pages into subfolders. Given that ASP.NET Core derives a page URL from the page’s physical location, the URLs are hierarchical and better describe the different features and regions of an application. It’s also easy to look at the UI, and find the Razor page responsible for a particular screen.

What Are Razor Pages Missing?

Razor pages have a lot to offer, including features I haven’t detailed yet, like automatic anti-forgery token validation.

There are also features that do not exist in Razor pages, despite what the ill-informed say.

There is no viewstate in Razor pages. There are also no synthetic initialize or click events. A Razor page is no more stateful than a controller with it’s ModelState data structure. In short, Razor Pages aren’t related to Web Forms or Web Matrix Web Pages. Razor pages are an authentic abstraction for programming the web.

Summary

Razor Pages are a welcomed refinement to the MVC framework and include many optimizations for sever-side HTML generation and form processing. Try them out before rushing to judgment!

The need to use the MVC framework is fading into the background with ASP.NET Core. Instead of MVC, we have Razor Pages for HTML apps, Controllers for 'REST' APIs, gRPC services for coupled APIs, and SignalR for real time communications.