Things I’ve Learnt This Week (5th March)

Week 6 of my series, sharing things I’ve learnt, read, watched and listened to, in the pursuit of expanding my knowledge about software development.

Things I’ve Blogged

Customising ASP.NET MVC Core Behaviour with an IApplicationModelConvention – In this post I cover details and demo the basics of creating custom conventions for ASP.NET MVC Core.

Things I’ve Learnt

UserSecrets API Changes

One of the changes coming due to the project.json to csproj move is a slight change needed on the UserSecrets API. In current project.json applications we can use the AddUserSecrets() extension method. This picks up the UserSecretsId from the project.json file and sets up the UserSecrets config using it. With the move to csproj this method’s implementation might pick up the wrong assembly and therefore not find the newly located UserSecretsId. To resolve this, the method now needs the assembly to be passed to into it.

There is a new generic call we can make we can use with looks like  .AddUserSecrets<Startup>() – This takes a class and will use the assembly where that class is located when calling the AddUserSecrets(assemblyname) method.

When ASP.NET Core 2.0 lands, the old API for AddUserSecrets() will be removed. Making it clear that ASP.NET Core 2.0 will require VS 2017 and support csproj only.

You can read more about these changes on Github here, here and here.

Things I’ve Read

Things I’ve Listened To

Things I’ve Watched

Customising ASP.NET MVC Core Behaviour with an IApplicationModelConvention

I’m currently building a number of ASP.NET Core API applications which together form a new product we’re developing. As we defined the requirements, we came up with a few behaviours that we wanted to apply across the APIs by default. Two examples that I’ll use in this blog post are, applying a prefix to all of our routes and securing all of the endpoints by default.

In the case of the route prefix we needed this in order to support sharing a single AWS application load balancer between the APIs. We have three API microservices working together as part of our system, and each needed its own unique prefix so that the load balancer could direct the traffic to the correct service. We use attribute routing across our APIs and wanted a way to be able to apply a prefix, without hardcoding it onto every controller.

The second requirement from our security discussions, was that we wanted every endpoint to be locked down to the most restrictive authorization policy by default, even when no authorization attribute is applied. We prefer this hardened by default behaviour to avoid the possibility of unsecured access when changes are made. Using this approach we open up access on endpoints on a case-by-case basis.

After a bit of searching on the Internet, followed by a dive into the MVC source, I found a set of interfaces that allowed us to begin customising how MVC Core behaves. Enter the following interfaces…

  • IApplicationModelConvention
  • IControllerModelConvention
  • IActionModelConvention
  • IParameterModelConvention

What are Conventions?

Conventions exist throughout MVC and allow us to work with the framework without having to specify everything manually. Conventions are behaviours that MVC will apply by default and we can lean on these conventions in many cases. An example is the fact that when defining routes in Razor we can use the Controller name without the “Controller” suffix each time. MVC will handle that by convention.

However, as we develop more complex applications, we may want to define our own rules and conventions, or customise the existing behaviours. The four interfaces listed above provide a mechanism to allow us to do just that.

How Can We Create Them?

To start developing a new convention, you create a Class which inherits from one of these interfaces. When the MVC application is loading, we can register these new conventions, which will then be applied as MVC builds up a model in memory that represents the application. Each of these interfaces gets more specific in terms what they target and they are applied in this order as well. More specific conventions will override less specific conventions set higher up in the application model.

In this post I’ll demonstrate creating a couple of conventions. In order to keep everything easy to understand I have reduced the complexity of the conventions themselves as I want to focus on the mechanics of how we create them.

Defining the API

For this example I’ve put together a very basic single Controller API that will allow me to demonstrate the conventions. Here is what the Controller looks like.

Route Prefix Convention

As I mentioned above, in our APIs we use attribute routing to define the routes for all of our endpoints. I prefer this to the route builder approach as it makes documenting the API more explicit in my view. It’s easier for someone working with the code to see the paths that we are using, and also means we can use tools like Swashbuckle to build a swagger interface over our endpoints.

As I also stated, we host our APIs behind an AWS application load balancer. In order to share a load balancer, we need the traffic for each API to come in from a distinct path under a single shared domain. This allows us to use the AWS load balancer path routing to direct the traffic into the correct API application. Due to the way we engineer things, we wanted to be able to potentially update this path in the future, so we didn’t want it to have to be defined as part of the route attributes.

In our case a solution we came up with was to use a convention that would inspect the routes applied to each Controller, updating them at startup, so that the correct prefix was applied.

For this convention we will inherit from IControllerModelConvention which will allow us to work with the Controller and below. Since the attributes are defined on the Controllers, this is perfect for our needs. The convention I ended up using looks like this…

This is a simplified version of the convention we used in our application but it’s fine for demonstrating the main principles. The first thing to highlight here is the AttributeRouteModel I’m defining at the top. An AttributeRouteModel allows us to programmatically define the properties that make up a RouteAttribute that gets applied on Controllers and Actions. I’m defining one here that contains the template prefix I want to use. In a real world application, I define this template in our configuration and pass it into the RoutePrefixConvention on construction. But to keep this blog post focused I skipped those elements and hard code it as part of the Class.

The IControllerModelConvention interface defines a single void method called Apply. We use this to apply our behaviours to the Controllers in our application. The method accepts a ControllerModel parameter which gives us access to properties on each controller as the application starts up.

Now that we have the ControllerModel we use a collection on it called Selectors, which allows us to inspect the AttributeRouteModel applied to the controller. In the case where we find an AttributeRouteModel, it means the controller already has a Route applied to it. In this case we want to prepend the route defined on the Controller attribute with our prefix. We do this using the static CombineAttributeRouteModel method, which takes two AttributeRouteModels and combines them into a new model. In our example, I have used the prefix first and then applied the value that was defined explicitly on the controller. In the case of our HomeController this means that MVC now understands this to take the template “Prefix/Home” in its route definition. Where we do not find an existing AttributeRouteModel we can simply set the value of this on the selector to our defined prefix. Therefore any Controller without a route attribute will be considered to operate under the “Prefix” path.

Now when our application starts up, it gets configured using our required prefix across all controllers. In our case this means we can rely on the fact that our endpoints will all operate under a single prefix which our load balancer can use to route the traffic. Developers do not need to manually include the prefix value in the controller route and we avoid the risk that they may forget to do so. We also only need to maintain the prefix value in a single place, rather than having to update each controller if this prefix were to change in the future.

Authorization By Default Convention

Another example of a convention we wanted to apply in our APIs was that by default they would be secured to the highest level even when no AuthorizeAttribute is applied. There are various ways this might be achieved but we decided that a convention worked nicely for our requirements. By having actions secured by default it means there is no risk of a new Action being added that could inadvertently be left unsecured if the developer forgets to include an AuthorizeAttribute.

A simplified example of how we achieved this is as follows:

In this convention, since we want to work with Actions we have inherited from the IActionModelConvention interface. Every action in our application runs through this convention, applying the new convention as necessary.

Again we have an Apply method, this time accepting an ActionModel, representing the Action. First we check if we need to apply our convention to the Action. In our case, we only want to apply the AuthorizationPolicy if the Action does not have one specified or has not been explcitly marked as allowing anonymous access. In cases where these attributes have been set we assume the developer has controlled the access as required. Our convention only applies to Actions if they are missing any specific Authorize or AllowAnonymous attributes.

If we do find an action missing the attributes we create an AuthorizationPolicy and apply it with an AuthorizationFilter to the Action. Again, this example is over simplified in that our actual code defines many policies during startup, and in our case we pass in a restrictive policy into the Convention using it’s constructor. The code needed to do that is outside of what I wanted to demonstrate in this post.

For my example HomeController, the Index action does not specify any Authorization values. So by default this will now be secured by convention with a require authenticated user policy. If we access it without being authenticated we receive a 401 result back. The OpenEndpoint Action however will allow unauthenticated users since we have explicitly defined it to AllowAnonymous.

Wiring It Up

The final piece of work is to include our custom conventions so that MVC knows about them and can use them when it builds up its application model. We do this by adding the conventions to a Conventions collection on the MVC options during service registration. Here is the ConfigureServices method that I’ve used in this demo.

On the AddMvcCore extension we can work with the MvcOptions object. We simple call Add on the Conventions collection to register our new conventions.

In Summary

The convention interfaces provide a powerful and simple way to begin defining bespoke behaviour on your applications. They provide a nice single place for customisation to occur and are quite simple to work with. One consideration to keep in mind is that they might make your application confusing to new developers who expect it to work using the MVC default conventions. Developers need to be aware that custom conventions are being applied and how those may override the default behaviour of your application.

Things I’ve Learnt This Week (19th February)

Week 4 of my series, sharing things I’ve learnt, read, watched and listened to, in the pursuit of expanding my knowledge about software development. A slightly shorter set of links this week, things have been fairly busy so I’ve had less time to keep up with all of the fantastic content.

Things I’ve Learned

That I enjoy technical speaking! This week, I delivered a talk to a room of developers about ASP.NET Core. It’s a popular topic which I think generated the interest and high attendance. I’m quite shy and an introvert by nature, and I generally hate any form of public speaking so presenting a talk is way out of my comfort zone. However, it’s something I’ve been keen to work on; It’s a great way to share information and helps me learn as well. I had the usual nerves leading up to the talk, but I’d practised and refined it over a number of rehearsals, to the point that I was confident in what I was delivering. The talk also included a 30 minute live demo, which thankfully worked perfectly thanks to many practice runs. As soon as I got going I started to feel better and by the end, was on a bit of a natural high. I’ve had some very nice feedback from some of the attendees and I’m encouraged to work on future talks as well as hopefully sharing this one with a wider audience in the future. If I was asked for advice from other developers looking to prepare a technical talk, it would be practice, practice, practice! Having gone through my slides, rehearsing the full talk at least 10 times, I knew what I was going to say and that allowed me to present confidently.

Things I’ve Read

Things I’ve Listened To

Things I’ve Watched

Things I’ve Learnt This Week (12th February)

Week 3 of my series, sharing things I’ve learnt, read, watched and listened to, in the pursuit of expanding my knowledge about software development.

Things I’ve Learned

Dependency Injection in Middleware

An important thing to consider when building custom Middleware in ASP.NET Core – If you are injecting a dependency into the constructor of your Middleware it may have unwanted effects if that dependency is expected to be a scoped/transient resource. The Middleware is constructed once for the app lifetime during Startup and not recreated for every request. If you want a transient/scoped dependency, inject it into the Invoke method’s parameters which is called once per request and therefore will give you the correctly scoped instance of your dependency every time.

Dependency Injection Lifetime Fun

A little long for this weekly post, I wrote up a dedicated post this week about some “fun” I had tracking down a range of errors we were seeing in some code this week. Spoiler alert… scoped lifetime dependencies inside a singleton lifetime registration = not good!

I also published a post this week entitled “Migrating from .NET Framework to .NET Core” which describes the process I followed to move an ASP.NET Core application from the full .NET framework onto .NET Core, enabling cross-platform development.

Things I’ve Read

In no particular order here’s some of the blogs and posts that I’ve read this week.

Things I’ve Listened To

Things I’ve Watched

Tools

  • ChangemakerStudios – Papercut – A useful local SMTP receiver for testing email in your code on localhost. This week I was adding some email functionality to one of our services and I wanted to test the flow locally in development. This tool was really easy to use and worked perfectly for my requirements.