Avoiding the Service Locator Pattern in ASP.NET Core

Thursday, February 18, 2016 by K. Scott Allen

Six years ago, Mark Seeman authored a post titled “Service Locator is an Anti-Pattern”. All of the problems Mark demonstrated back then are still problems today. I’ve been pointing developers to Mark’s post because the service locator anti-pattern is a pattern I’ve seen creep into some early ASP.NET Core code bases. The code usually looks something like the following:

var provider = HttpContext.ApplicationServices;
var someService = provider.GetService(typeof(ISomeService));

It is easy to use the service locator pattern in ASP.NET. Nearly every type of component, from controllers to views, have access to the new HttpContext, and HttpContext exposes a service provider via ApplicationServices and ReqeustServices properties. Even though HttpContext facilitates the service locator pattern, I try to avoid using these properties. 

The service locator pattern typically appears in applications that have not fully embraced an inversion of control container, or dependency injection. Yet, the new ASP.NET offers these features from the very beginning of an application, meaning it is just as easy (or easier) to avoid the service locator pattern.

For Startup

In “How To Stop Worrying About ASP.NET Startup Conventions”, I remarked how the Configure method of the Startup class for an application is an injectable method. The runtime will resolve any services you need from the application container and pass them along as arguments to this method.

public class Startup
{
    public void ConfigureServices(IServiceCollection services) { }
 
    public void Configure(IApplicationBuilder app,
                          IAmACustomService customService)
    {
        // ....   
    }        
}

For Middleware

Custom middleware has two opportunities to ask for services. Both the constructor and the conventional Invoke method are injectable.

public class TestMiddleware
{
    public TestMiddleware(RequestDelegate next, IAmACustomService service)
    {
        // ...
    }

    public async Task Invoke(HttpContext context, IAmACustomService service)
    {
        // ...
    }    
}

Constructor injection is good for those services you can keep around for the duration of the application, while Invoke injection is useful when you may need the framework to give you a service instance scoped to the current HTTP request.

For Controllers

Constructors are injectable.

public class HelloController : Controller
{
    private readonly IAmACustomService _customService;

    public HelloController(IAmACustomService customService)
    {
        _customService = customService;
    }

    public IActionResult Get()
    {
        // ...
    }
}

For Actions

You can also ask for a dependency in a controller action using the [FromServices] attribute on a parameter. Instead of model binding the parameter from the HTTP request environment, the framework will use the container to resolve the parameter. 

[HttpGet("[action]")]
public IActionResult Index([FromServices] IAmACustomService service)
{            
    // ...
}

For Models

[FromServices] also works on model properties. For example, the following action needs an instance of a TestModel.

public IActionResult Index(TestModel model)
{
    // ...
}

The TestModel class class looks like the following.

public class TestModel
{       
    public string Name { get; set; }

    [FromServices]
    public IAmACustomService CustomService { get; set; }
}

For property injection to work, the property does need a public setter. Also, constructor injection does not work for model objects. Both of these facts are lamentable.

For Views

In “Extending Razor Views”, I made the argument that the @inject directive should be the only extensibility mechanism you should use.

@inject IAmACustomService CustomService;
 
<div>
    Blarg   
</div>

For Everything Else, Even Filters

For every other type of component there is almost always a way to have constructor injection work. This is true even for action filters, which have been notoriously difficult in previous versions of ASP.NET MVC. For more on DI with filters specifically, see Filip’s post “Action Filters, Service Filters, and Type Filters”.

Back In Time with Windows IoT

Tuesday, February 16, 2016 by K. Scott Allen

After graduate school my first job was programming in assembly language for an 8 bit Hitachi CPU. The software would fire infrared light through organic substances to measure the amount of moisture or protein inside. Even at the low level of opcodes and operands, software (and hardware) still presented auras of mystery for me at this early point in my career. Every day presented a challenge and the opportunity for a thrill when bits aligned well enough to work.

I’ve largely ignored the Raspberry Pi since it first appeared. I bought one 2 years ago to give my youngest son some inspiration to write Python code. The plan worked. But, I’ve never bought one for myself, and assumed a “been there, done that” attitude.

Then one weekend, on a whim, I threw a CanaKit Raspbery Pi 2 kit into my shopping cart. Even though I had been there and I had done that, it was a long time ago. And, those being good times, maybe I could relive them a bit.

Running with Windows IoT

Growing up in a county with blue laws, I’m still astonished when a package arrives on a Sunday. Who needs delivery drones when sentient employees of the US Postal Service deliver packages with a smile?

Thanks to the Windows IoT Dashboard, I had the Pi booted into Windows 10 only 20 minutes after receiving the package.

 

Windows 10 IoT Dashboard 

The decision to use Windows 10 was an impulse decision. In hindsight, perhaps not the best decision for what I wanted to do with the Pi. Linux distros on the Pi give a general purpose operating system with the option to apt-get nearly any application, driver, or toolset. Win10 feels like an operating system built for a specific purpose – running Windows Universal application prototypes deployed by Visual Studio. Don’t think of Win10 IoT as Windows on an ARM processor. Win10 IoT has no Cortana, or start menu, or even a shell, for that matter. Although, it does listen for ssh connections out of the box.

SSH to Rasberry Pi2 with Win10 IoT

Win10 IoT has limited hardware support and does not support the WiFi dongle provided with the CanaKit I bought. I had to plug in an Ethernet cable before I was able to reach the Pi with ssh. Win10 does support a $10 Realtek dongle, which I purchased days later and works well. If I knew before what I know now, I would have checked the hardware compatibility list up front, but my impulse buys rarely exhibit such caution. 

You can also connect to Win10’s built-in web site on port 8080. This is the easiest way to configure devices like the WiFi dongle, although you can also run netsh commands through ssh or remote Powershell.

 

Windows 10 Iot Config

 

Running .NET Core

Although running a Windows Universal app was tempting, I wanted to use .NET Core (currently dnx) to get some bits working on the Pi. The setup is remarkably easy. The first step is getting some Core CLR bits onto the development machine.

dnvm install latest -r coreclr -arch ARM -u

The key options here is –arch ARM. Note there is currently an issue here, as dnvm will use the new install to set the process path. Since the path is for an ARM architecture, dnx is unusable until you dnx use a runtime with the appropriate architecture. Then, once you have an application written, be it command like or web application, use dnu (currently) to publish the application, including the runtime.

dnu publish --out "c:\out\HelloPi2" --runtime dnx-coreclr-win-arm.1.0.0-rc2-16357

The above command packages the application, including source and the full runtime framework. There output folder will contain ~45MB of files, which is why the --native switch will be useful in the future when it works properly. Deployment is a simple xcopy to the Pi file share, and execution only requires finding and running the .cmd file dnu creates in the approot folder.

In Conclusion

Working with Windows IoT and the Pi is not quite what I remember from the old days of EEPROM burners and oscilloscopes. It’s too easy. But, there still is some magic in fiddling with a relatively raw piece of hardware. 

How To Stop Worrying About ASP.NET Startup Conventions

Tuesday, February 9, 2016 by K. Scott Allen

There are 2 kinds of developers. Those who love conventions and those who loathe conventions. The former group sees conventions as a means to remove boilerplate code and expose the essence of software by avoiding ceremony. The later group tends to view conventions as dangerous magic. It’s also the later group, I’ve found, which tends to dislike the Startup class in ASP.NET Core applications.

public class Startup
{
    public void ConfigureServices() { }
    public void Configure() { }
}

Questions around Startup generally revolve around the following themes:

1. Why isn’t there a required interface available for Startup to implement?

2. How do I know what methods are needed and what parameters the methods will accept?

The short answer to both of these questions is that conventions offer more flexibility than contracts.

Naming Conventions

Programming against conventions is frustrating when you don’t know the conventions. The software won’t behave correctly, and in many convention oriented systems you won’t see any error message or know how to start debugging. Conventions are indistinguishable from magic.

Fortunately, for the startup scenario, the runtime does give you some actionable error messages when you miss a convention. For example, if you don’t have a proper class name for the startup code, ASP.NET will give you the following.

A type named Startup could not be found

Here, the runtime will not only tell you what is missing, but also give you hints where you can find some wiggle room. You can have a dedicated startup class for any given environment, and use Startup itself as a default fall back. StartupDevelopment, StartupProduction, and StartupYourEnvironmentNameHere can all live in the same project and provide the startup configuration for their given environment name.

The same convention also applies to the Configure method in a startup class. In other words, once the runtime locates the startup class for the application, it will look for Configure and ConfigureServices methods that optionally have the environment name as a suffix.

A public method named Configure could not be found

One difference between Configure and ConfigureServices is that ConfigureServices is entirely optional. If you don’t provide the method, the runtime will carry on with only default services installed.

These types of conventions are impossible to enforce using interfaces. Attributes could make the purpose of a class more explicit, but attributes would add ceremony with little benefit.

Versus Interfaces

Another difference between the Configure and ConfigureServices methods is how the ConfigureServices method can only take a parameter of type IServiceCollection. The Configure method, on the other hand, is an injectable method. You can take any number and types of parameters in Configure as long as the underlying IoC container can locate a service to populate the parameter.

public class Startup
{
    public void ConfigureServices(IServiceCollection services) { }

    public void Configure(IApplicationBuilder app,
                          IApplicationLifetime lifetime,
                          IHostingEnvironment hostingEnvironment,
                          IApplicationEnvironment applicationEnvironment)
    {
        // ....   
    }        
}

The type of flexibility demonstrated by Configure is impossible to describe using a C# interface, and it is not the sort of flexibility you want to lose just to have a simplistic compile time check, at least not when the error messages are so explicitly good. Don’t worry about the conventions, the runtime will let you know when you goof.

The New Fetch Standard

Monday, February 8, 2016 by K. Scott Allen

The XMLHttpRequest object has been around, in one form or another, since 1999. XHR has been a key ingredient in most web applications for well over a decade now. During that time various libraries have wrapped the API to make XHR more palatable and easier to use, while vendors have extended the capabilities of XHR to support binary data, cross origin requests, and progress events. It’s been quite the ride, but the future is fetch.

Think of fetch as a modernized XMLHttpRequest. The raw API is easier to use, and all starts with a global fetch method.

var movie = {
    id: 1,
    title: "Star Wars"
};

fetch("/movies", {
    method: "put",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify(movie)
}).then(function(response) {
    return response.text()
}).then(function(result) {
     console.log(result);
});
    

With promises now an official part of the JavaScript language, it is nice to see standard APIs using promises instead of callbacks.

Browser support for fetch is coming along (I ran the above sample in Chrome 47), although the API is still a work in progress. The API allows us to influence the caching mode directly ({cache:”reload”}, as one example), which is good, but timeouts and deadlines are still open issues and not yet in the spec.

Some of My Favorite Maps

Friday, February 5, 2016 by K. Scott Allen

I remember being a kid in the back seat of my parents car on a 10 hour jaunt to Indiana when I first discovered the joys of a Rand McNally Road Atlas. I used to keep track of our progress along the highway, but also trace routes to destinations I’d only heard of, and marvel at the complexity of inner city road systems. I think the experience was good for me as today I have a decent sense of direction. I also learned, years before driving myself, that odd numbered roads in the US typically run north and south, while even numbered roads run east and west. Later in life I learned to ignore all directional conventions when in southern New Jersey.

Most of the maps I use today aren’t as tactile as the old road atlas, but I still find maps educational and in some ways, inspirational, too. Here are a few places I keep bookmarked.

Wikimapia

Wikimapia combines the the imagery and cartography of Google and Bing with peer-produced content ala Wikipedia. The older I get the more I’m interested in the history of the places I visit, and Wikimapia is starting point for location-based research. On my last trip I investigated the Canary Wharf district of London and tried to find out why the district is on a piece of land known as the Isle of Dogs, but there are only hypotheses about the etymology of the name. Canary Whaf in Wikimapia

Earth

A globe built with SVG and canvas elements provides a visualization of winds, weather systems, and ocean currents. Use the menu in the lower left to see everything from surface winds to ocean waves and jet steams including, at this time of year, the polar night jet.

Source code is available from Cameron Beccario on github.

image

Flightradar24

A real-time flight tracker. Ideal for those situations when you want to know who is flying overhead

Flightradar24

MarineTraffic

A real-time vessel tracker. Ideal for those situations when you want to know who is sailing nearby.

MarineTraffic

Wundermap

The weather map from the Weather Underground is the first map I check for weather conditions. Not only can you fill the map full of information, the web site itself doesn’t use terrifying headlines and bizarre ads like some other weather sites.

Weather Undergrounds Wundermap

Extending Razor Views in ASP.NET Core

Thursday, February 4, 2016 by K. Scott Allen

If you need to add capabilities to Razor views in ASP.NET Core, there are a few different approaches you can take.

@inherits

By default, a Razor view inherits from RazorPage<T>, where T is the type of model as set by the @model directive. With no XML based configuration around, the @inherits directive is now available to change the default base class. Currently, @inherit only appears to work when the base class of the base class is RazorPage<object>, but using a custom base class does give you the ability to define additional properties and methods for a view to consume.

@inherits BaseView
<div>
    ...
</div>
public abstract class BaseView : RazorPage<object>
{              
    public bool IsAuthenticated()
    {
        return Context.User.Identity.IsAuthenticated;
    }
}

Note that one downside to @inherits (other than encouraging a messy inheritance hierarchy) is that the @inherits and @model directives are mutually exclusive, so you can’t use both in the same view. Thus, the “one base class to rule them all” approach is unfeasible. Fortunately, there are better approaches.

@functions

The @functions directive is similar to the @helper directive in previous versions of Razor. ASP.NET generates a class after parsing a view, and code inside of the @functions block are added as members to the class. In most cases you’ll want to add only functions to the generated class, but it is technically possible to add fields, properties, and events.

@functions
{
    public bool IsAuthenticated()
    {
        return Context.User.Identity.IsAuthenticated;
    }

    readonly string message = “test”;
}

<div>
    @if (IsAuthenticated())
    {
        <div>...</div>
    }
    else
    {
        <div>@Message</div>
    }
</div>

Currently there doesn’t appear to be an easy way to share @function blocks across multiple views, but there is one more option, which is, I think, the best option.

@inject

The @inject directive creates a new property in the generated code for a view. ASP.NET will set the property by asking the IoC container for a service that matches the type of the property. With the following Razor code, we’ll inject the IHostingEnvironment service which is available in every web application by default, and use the service to display the current environment name.

@inject IHostingEnvironment Host;


<div>
    Running in @Host.EnvironmentName
</div>

The class ASP.NET generates for a view with an @inject directive looks like the following:

[Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute]
public IHostingEnvironment Host { get; private set; }

You might see @inject as an abuse of the MVC design pattern. Why inject services directly into a view when I could use the same services inside a controller and build a proper model in a testable manner? A fair criticism, and ‘@inject abuse’ will be a design flaw to avoid. However, a view does need to execute code and there are a reasonable set of services that can help a view. For example, a localization service. In fact, several in-built capabilities of Razor views are injected as services by default, like the Url, Html, and Component helpers. You’ll find the following properties in the code by default for every Razor generated view.

[RazorInjectAttribute]
public IUrlHelper Url { get; private set; }

[RazorInjectAttribute]
public IViewComponentHelper Component { get; private set; }

[RazorInjectAttribute]
public IJsonHelper Json { get; private set; }

[RazorInjectAttribute]
public IHtmlHelper<dynamic> Html { get; private set; }

Having an IUrlHelper injected into a view instead of being inherited from a base class means we are using composition instead of inheritance, which gives us more flexibility and extensibility points than ever before.

But wait, there’s more!

@inject and _ViewImports

ASP.NET core adds a new magic file by the name of _ViewImports. Similar to _ViewStart, this is a file that when placed into a folder will influence all views in the folder hierarchy. One reason for _ViewImports to exist is to provide some default using statements to bring namespaces into scope for all views in the same hierarchy (again, because we have no XML configuration to work with and XML is where we used to specify default namespaces). However, you can also use _ViewImports to register tag helpers, and the @inject attribute also works from _ViewImports. Let’s say you place the following code into a _ViewImports.cshtml file in the Views folder itself. The namespaces and injected properties are available for every view in the Views folder, and all child folders.

@* These namespaces now available to all views *@
@using Microsoft.AspNet.Hosting

@* These services now available to all views *@
@inject IMyViewHelpers Helpers;
@inject IHostingEnvironment Host;

Summary

Forget @functions and don’t use @inherits. The @inject directive allows you to compose functionality into Razor views in a flexible, extensible, and testable manner.

Spying on Razor View Compilation

Wednesday, February 3, 2016 by K. Scott Allen

Sometimes the best way to understand code is to compile and execute the code. In this scenario I needed to understand a bit more about view compilation in ASP.NET Core. Here is a simple spy to track the file information and compilation results for each razor view.

public class RazorCompilationServiceSpy : IRazorCompilationService
{
    private IRazorCompilationService _inner;
    private IList<CompileEntry> _log;

    public RazorCompilationServiceSpy(ICompilationService compilationService,
                                      IMvcRazorHost razorHost, 
                                      IOptions<RazorViewEngineOptions> options)
    {
        _inner = new RazorCompilationService(compilationService, razorHost, options);
        _log = new List<CompileEntry>();
    }

    public CompilationResult Compile(RelativeFileInfo fileInfo)
    {
        var result = _inner.Compile(fileInfo);
        _log.Add(new CompileEntry { FileInfo = fileInfo, Result = result });
        return result;
    }

    public IEnumerable<CompileEntry> CompilationLog
    {
        get
        {
            return _log;
        }
    }

    public class CompileEntry
    {
        public RelativeFileInfo FileInfo { get; set; }
        public CompilationResult Result { get; set; }
    }
}

The easiest way to grab information from the class is to register the class as a singleton during Startup::Configure.

 services.AddSingleton<IRazorCompilationService, RazorCompilationServiceSpy>();

Note that the real RazorCompilationService runs as a transient service in a typical ASP.NET application, but for this simple experiment we are ignoring all the terrible threading problems that might arise using singletons and regular collection classes like a List<T>.

Inside a Razor view we can use the following code to see the compilation results.

@using Microsoft.AspNet.Mvc.Razor.Compilation;

@inject IRazorCompilationService CompilationSpy

@functions {
    public RazorCompilationServiceSpy GetCompilationSpy()
    {
        return (RazorCompilationServiceSpy)CompilationSpy;
    }
}

<section>
    <h3>Compilation Results</h3>

    @foreach (var result in GetCompilationSpy().CompilationLog)
    {
        <h4>@result.FileInfo.RelativePath</h4>
        <pre>@result.Result.CompiledContent</pre>

    }

</section>

Which yields output like the following:

image

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!