Custom From* attributes for controller action methods in ASP.NET Core

Implementing custom From* attributes for controller action methods in ASP.NET Core.

Custom From* attributes for controller action methods in ASP.NET Core

Recently I was going through some controllers and noticed a lot of code that was reading claims from ClaimsPrinciple. If you ever worked with claims in ASP.NET Core then code like User.FindFirst(...) might be familiar. All that the method does is that it will find the first claim that matches the type you want. You might have also noticed that, if you wanted to unit test some method in the controller that uses claims, it actually requires a quite a few extra lines of code to achieve that. You have to create ClaimsPrincipal, ClaimsIdentity and Claims and then set everything on the HttpContext of your ControllerContext.

I stopped for a second and said to myself: "It would be nice if I could just get the required claim as a method parameter". And then I realized that it might not be that hard to actually achieve that! Let's see what we have to do to implement a custom [FromClaim] attribute.

Representing our source of data for binding

We will start by creating a BindingSource for our source of data. This is needed when we want to bind our claim to the parameter of our controller action method.

We will use the BindingSource that we have created in the following steps.

Creating the value provider

The next very important step is to create the value provider. The value provider is the class where the actual claims will be read from the ClaimsPricinpal. We will base our new ClaimValueProvider on the BindingSourceValueProvider since we want to bind  our claims to parameters in our controller action methods.

In our ClaimValueProvider we will need a BindingSource which will be the one we created for claims and a ClaimsPrincipal from which we will read the required claim.

In the ContainsPrefix(...) method, we will check whether the required claim is available.

In the GetValue(...) method, we will return the first claim that matches the required claim type.

This is all we need to do in the value provider. As you can see, you can easily unit test this class, since it does only a couple of small things.

Creating the value provider factory

Now when we have implemented the ClaimValueProvider, we will need something that will create it with correct BindingSource and ClaimsPrincipal. This will be done by implementing a new IValueProviderFactory which we will call ClaimValueProviderFactory.

We will pass our claim-specific BindingSource and also pass the ClaimsPrincipal from the HttpContext that is available in the ValueProviderFactoryContext which we get.

Once you have your provider created, you have to also add it into the available value providers in the ValueProviderFactoryContext.

The last step is to hook up our ClaimValueProviderFactory into available value provider factories which ASP.NET Core uses. You can do that in the AddControllers[WithViews](...) method in ConfigureServices(...).

The last but not the least, our custom [FromClaim] attribute

So far we have implemented all the logic that will extract the claim from the ClaimsPrincipal and hooked up everything in ASP.NET Core. What is missing is our [FromClaim] attribute itself.

Our attribute will implement two interfaces:

  1. IBindingSourceMetadata  - this will specify which binding source will be used for binding
  2. IModelNameProvider - this will specify the model name, this is the key that we will get in the value provider as a parameter

We will also add a constructor which receives a claim type, so we have to specify the claim type when we use it in our controller action method, e.g. [FromClaim("")] .

Using our new attribute in controller action method

Now when we have everything implemented, we can easily use our new attribute in the controller action method.