ASP.NET Core RC2 IOptions Configuration: An alternative to Enumeration

As of today the Enumeration nuget package from the good folks over at Headspring does not work with ASP.NET Core RC2 (formerly known as ASP.NET 5).

There is an alternative that while not exactly the same does allow for you to have a data structure that contains the data you need access to through its properties and nested types. The solution takes advantage of the configuration framework that is now part of ASP.NET Core. You can read the official documentation here.

My problem
With the new ASP .NET Identity system roles have become deprecated. The new hotness is to save everything as a claim. My claims (permissions) list was going to be relatively static and not change very often so I didn’t want to store them in a database of some kind and look them up with every request when doing authorization checks.

Create a JSON file
First we need to put our data into some type of format that can be used by the configuration framework. XML, JSON, and INI files are supported. I will be using JSON. Here is what my file looks like:

{
  "Claims": {
    "Admin": {
      "UserManagement": {
        "ViewUsers": {
          "name": "View Users",
          "id": 100
        },
        "CreateUsers": {
          "name": "Create Users",
          "id": 110
        },
        "EditUsers": {
          "name": "Edit Stats",
          "id": 120
        }
      }
    },
    "user": {
      "products": {
        "EditProducts": {
          "name": "Edit Products",
          "id": 200
        },
        "ViewProductReports": {
          "name": "View Product Reports",
          "id": 210
        }
      }
    } 
  }
}

Next save the JSON file into the root of the project:
claimsInRoot

Create a Data Structure
After creating your JSON file you will want to generate a data structure for it.

Now hold on there partner! Not so fast. Before you go off and start building out some classes by hand you should try this nifty little trick:
1. Highlight your data from the JSON file and copy it to the clipboard.
2. Create a new class file and save it wherever you want. I put mine in the models folder.
3. Delete the class declaration and leave the namespace.
4. Set your cursor between the curly braces of the name space and then go to Edit > Paste Special > Paste JSON as classes. And voila!

This is what was generated for me:

namespace IOptionsSample.Models
{

    public class Rootobject
    {
        public Claims Claims { get; set; }
    }

    public class Claims
    {
        public Admin Admin { get; set; }
        public User user { get; set; }
    }

    public class Admin
    {
        public Usermanagement UserManagement { get; set; }
    }

    public class Usermanagement
    {
        public Viewusers ViewUsers { get; set; }
        public Createusers CreateUsers { get; set; }
        public Editusers EditUsers { get; set; }
    }

    public class Viewusers
    {
        public string name { get; set; }
        public int id { get; set; }
    }

    public class Createusers
    {
        public string name { get; set; }
        public int id { get; set; }
    }

    public class Editusers
    {
        public string name { get; set; }
        public int id { get; set; }
    }

    public class User
    {
        public Products products { get; set; }
    }

    public class Products
    {
        public Editproducts EditProducts { get; set; }
        public Viewproductreports ViewProductReports { get; set; }
    }

    public class Editproducts
    {
        public string name { get; set; }
        public int id { get; set; }
    }

    public class Viewproductreports
    {
        public string name { get; set; }
        public int id { get; set; }
    }

}

Setup the IOptions Configuration
Now that we have our data in a JSON file and our data structure to access it lets wire up the project to make use of it. To do that we need to go into the new startup class which is located in the root of the project.

In the constructor add the new claims.json file to the config builder.

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    .AddJsonFile("claims.json", false, true);

Next in the ConfigureServices() method add these two lines anywhere ( I put mine at the top of the method):

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    services.Configure<Claims>(Configuration.GetSection("Claims"));
    
    //Other code.....
}

Get the nuget package
For the mapping to work we will need to add the necessary nuget extensions package. Right click the project and install the package below:

Microsoft.Extensions.Options.ConfigurationExtensions

Now lets use it
To make use of our new claims we use dependency injection! Add it to the constructor of a controller or where ever you want and it will be available for you to use. Just as an example I am going to add it to my HomeController.

public class HomeController : Controller
{
    private readonly Claims _claims;

    public HomeController(IOptions<Claims> claims)
    {
        _claims = claims.Value;
    }

    public IActionResult Index()
    {
        var claimId = _claims.Admin.UserManagement.CreateUsers.id;
        ViewData["CreateUsersID"] = claimId;

        return View();
    }
}

ASP.NET Core has a new lightweight DI framework built in. When we configured our service above we were essentially setting up our IOC mapping so that when we asked for IOptions in the constructor the frame work would know what to return.

Now we have access to the claims list and we can use it when creating policies for authorization.

Leave a Reply