# How to restrict serialized properties with Json.NET and Web API 2.0 using a custom ContractResolver


<!--kg-card-begin: markdown-->
I recently were in a situation where I needed to hide parts of my models from unauthorized users.
 
I tried a few different things that weren’t that pretty or maintainable, but in the end I found a pretty simple solution.
 
To accompany this post I have made a very basic example project.
 
**Person.cs**

```csharp
public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string SocialSecurityNumber { get; set; }
}
```
 
**PersonController.cs**

```csharp
public class PersonController : ApiController
{
    [Route("api/persons")]
    public IEnumerable GetPersons()
    {
        return Database.GetPersons();
    }

    [Route("api/persons/{ssn}")]
    public Person GetPerson(string ssn)
    {
        return Database.GetPerson(ssn);
    }
}
```
 
**WebApiConfig.cs**

```csharp
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        // Force JSON responses only (no XML)
        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings =
            {
                Formatting = Formatting.Indented,
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
            }
        };
        config.Formatters.Clear();
        config.Formatters.Add(formatter);
    }
}
```
 
**JSON response at "/api/persons"**

```json
[
  {
    "name": "John Doe",
    "address": "Main Street 1",
    "dateOfBirth": "1971-06-10T00:00:00",
    "socialSecurityNumber": "654-84-6542"
  },
  {
    "name": "Jane Doe",
    "address": "Main Street 1",
    "dateOfBirth": "1975-08-13T00:00:00",
    "socialSecurityNumber": "342-45-1345"
  },
  {
    "name": "Sherlock Holmes",
    "address": "Baker Street 221b",
    "dateOfBirth": "1952-02-28T00:00:00",
    "socialSecurityNumber": "873-32-5284"
  }
]
```
 
Let’s say we wan’t to hide the `DateOfBirth` and `SocialSecurityNumber` for unauthorized users, as those informations are a bit personal.
 
I tried several different approaches, but none of them were that pretty. For example I tried with two different models for each original model – one for the authorized user and one for the unauthorized – but it lead to a lot of code duplication and I could already imagine the horror of maintaining this later on.
 
So I kept on looking for a better solution and then it hit me – why not just handle this at the serialization level?
 
**Json.NET** supports a simple way to dynamically determine if a member should be serialized by creating a method with the name `ShouldSerialize{MemberName}()` as illustrated below.

```csharp
public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string SocialSecurityNumber { get; set; }

    public bool ShouldSerializeDateOfBirth()
    {
        return HttpContext.Current.User.IsInRole("Staff");
    }

    public bool ShouldSerializeSocialSecurityNumber()
    {
        return HttpContext.Current.User.IsInRole("Staff");
    }
}
```
 
That’s one way to do it. But you quickly end up with a lot of code to write this way if you have a lot of properties and/or classes. There had to be a better way – and there is.
 
In the beginning of this post you can see the `WebApiConfig.cs`file wherein we create a new `JsonMediaTypeFormatter` with some custom serializer settings. The default `ContractResolver` serializes member names as they are written in our code. In C# we use PascalCase for public members while in JavaScript the convention is to use camelCase. That’s why I originally changed the `ContractResolver` to a `CamelCasePropertyNamesContractResolver` – this one serializses member names using the camelCase convention instead.
 
By extending this (or the `DefaultContractResolver`) we can change how and if members will be serialized. Beforewe do thatwe need to be able to identify which properties to restrict and how they should be restricted. This can be done pretty easily with some attributes. If you haven’t worked with attributes before, fear not, it’s pretty easy.
 
In my specific case I needed to be able to restrict one or more properties on a class if the current user didn’t have a specific role. For this I created two attributes: `JsonRestrictedAttribute` and `JsonRestrictedRoleAttribute`. To create a new attribute you just create a new class with a name that ends with Attribute and extend it from `System.Attribute`. On the new attributes I’m actually using another attribute to indicate where this new attribute can be applied and if it can be used multiple times on the same class/property. You can see my attributes below.
 
**JsonRestrictedRoleAttribute.cs**

```csharp
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class JsonRestrictedRoleAttribute : Attribute
{
    public string RoleName { get; set; }

    public JsonRestrictedRoleAttribute(string roleName)
    {
        RoleName = roleName;
    }

    public bool IsAuthorized(IPrincipal user)
    {
        return user.IsInRole(RoleName);
    }
}
```
 
**JsonRestrictedAttribute.cs**

```csharp
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class JsonRestrictedAttribute : Attribute
{ }
```
 
The new attributes doesn’t actually do anything themselves besides annotating your classes/properties/methods. The way you use them is through reflection, which we will get to soon.
 
We start out by extending `CamelCasePropertyNamesContractResolver` (if you don’t want the camelCase naming you can just extend `DefaultContractResolver` instead). Next we override the `CreateProperty()` method and then we want to insert our own predicate in the`JsonProperty`‘s`ShouldSerialize` property. This predicate determines if the property should be serialized.

```csharp
public class RestrictedContractResolver : CamelCasePropertyNamesContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization serialization)
    {
        var property = base.CreateProperty(member, serialization);

        // Check if the declaring type (the class declaring this property)
        // has a JsonRestrictedRole attribute
        var restrictedRoleAttribute = member.DeclaringType.GetCustomAttribute<JsonRestrictedRoleAttribute>();
        if (restrictedRoleAttribute != null)
        {
            // Check if the property has a JsonRestricted attribute
            var restrictedAttribute = member.GetCustomAttribute<JsonRestrictedAttribute>();
            if (restrictedAttribute != null)
            {
                // Set a new predicate that determines if
                // this property should be serialized or not
                property.ShouldSerialize = 
                    x => restrictedRoleAttribute.IsAuthorized(HttpContext.Current.User);
            }
        }

        return property;
    }
}
```

> **.NET Core** has moved parts of the Reflection API. You have to add in a `GetTypeInfo()` like this `member.DeclaringType.GetTypeInfo().GetCustomAttribute<JsonRestrictedRoleAttribute>()`

Before we just overwrite `ShouldSerialize` with our new predicate, we check for our new attributes. First we check the declaring class (the class that contains the current property) if it has our `JsonRestrictedRoleAttribute`. Next we check if the property itself has our `JsonRestrictedAttribute`. If that is the case, then we set `ShouldSerialize` to a new predicate, where we call the `IsAuthorized()` method of the `JsonRestrictedRoleAttribute` which then takes care of the logic for us.
 
Be aware that the `ShouldSerialize` predicate will be called each time the property is being serialized. If it didn’t this wouldn’t work. The `CreateProperty()` method, though, will only be called once and then cached for future use, so the authorization logic that is dependant on current information (like if the current user is logged in or has the right role) needs to be in the `ShouldSerialize` predicate.
 
Below you can see how to decorate the `Person` class with our new attributes, what needs to be changed in `WebApiConfig.cs` to use our new RestrictedContractResolver and at last how the output then looks like, when the current user does not have the **Staff** role.
 
**Person.cs**

```csharp
[JsonRestrictedRole("Staff")]
public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }

    [JsonRestricted]
    public DateTime DateOfBirth { get; set; }

    [JsonRestricted]
    public string SocialSecurityNumber { get; set; }
}
```
 
**WebApiConfig.cs**

```csharp
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        // Force JSON responses only (no XML)
        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings =
            {
                Formatting = Formatting.Indented,
                ContractResolver = new RestrictedContractResolver(),
            }
        };
        config.Formatters.Clear();
        config.Formatters.Add(formatter);
    }
}
```
 
**JSON response at "/api/persons"**

```json
[
  {
    "name": "John Doe",
    "address": "Main Street 1"
  },
  {
    "name": "Jane Doe",
    "address": "Main Street 1"
  },
  {
    "name": "Sherlock Holmes",
    "address": "Baker Street 221b"
  }
]
```
 
That’s it. Not that complicated after all and it is now easy to restrict parts of your models by just adding the `JsonRestricted` attribute to the properties and the `JsonRestrictedRole` attribute to the class itself.
 
This can easily be extended or changed for other purposes or with more advanced logic to fit your needs.
 <!--kg-card-end: markdown-->
