0

Let's imagine, that I have a class

public class Foo
{
  public int Prop1 { get; set; }
  public int Prop2 { get; set; }
  public int Prop3 { get; set; }
}

And imagine, that in some controller FooController I'm creating a List<> of such classes Foo, populating it with data, serializing it with Newtonsoft.Json and sending to client.

It's okay, there is no problems.

But, also I have per-user permissions system, which says that User1 can't see data of Prop1 and User2 can't see data of Prop3. And I have a lot of such classes Foo and a lot of permissions for different users of my system. And, to disallow users to see data from not allowed columns I decided to interrupt json serialization and exclude not allowed for user colums from JSON serialization.

For the moment it is already written custom JsonConverter, which allow me to do so. But, it is complicated (input class scan, dynamic accessor compilation, recursion and etc) and comparably to native newtonsoft's, slow.

Concerning above facts I want to ask if there is a easier way to achive the desired result? I mean, without creating custom JsonConverter remove any column from any serialized with json class.

Thanks for the answers!

UPDATE Followed the answer by @SebastianStehle. Extended my own mapper to map class to dictionary with an ability to exclude fields.

6
  • Instead of making us "imagine", why not post some actual code (and make sure you format that code!). Commented Aug 13, 2015 at 15:58
  • Why not just strip down the json Foo entries in the FooController based on the users permissions? Meaning: serialize all the necessary information for the model, but transform it based on the permissions. Is there a requirement that users can see raw json output or something? Commented Aug 13, 2015 at 15:59
  • No, I'm not allowed to send unallowed for user data because of our users are clever enough to interrupt posted data Commented Aug 13, 2015 at 16:07
  • OK, so this isn't on the back-end but some json service that feeds the front-end. I see your need to strip out items then. Have you considered separate models for each type of permission? For instance, we'd have a subclassed model that corresponds to the permission, or a model that reacts based on the users permission (on the 'gets{}'). Commented Aug 13, 2015 at 16:13
  • For now I hav about 30 different model classes. You advise me to subclass every class in any of possible combinations? No, that's not for my case 'cause I can't know which "columns" will be invisible for the next user. Commented Aug 13, 2015 at 16:26

2 Answers 2

1

Your problem is logic-oriented. You have different key-values and you wanna send it to your client depending on the scenario.

Newtonsoft.Json serializes json, it's its goal and it's not recommended to add logic in a serializer, it's harder to debug/maintain, keep the idea of one object/class doing one thing. It's called the single responsibility principle.

How/Where to add the logic ? I would recommend to use the command pattern with an object as argument. With that "pattern" you can easily add parameters (properties of your argument object) and add logic to your command. At the end you can return a list of key-values or an object and let json.net serialize it.

This solution may seem a little bit complicated but it's definitely useful in a long-term perspective. I can explain more in details how to implement it.

Last tip: you can use ASP.NET WEBAPI to serialize your objects for you (it uses json.net from the great Newtonsoft.Json)

Sign up to request clarification or add additional context in comments.

Comments

0

I see some other options:

  1. Leave the values empty. You can configure JSON.NET to not write properties with null or default value to the output stream:

    JsonSerializerSettings settings = new JsonSerializerSettings
    {
       DefaultValueHandling = DefaultValueHandling.Ignore,
       NullValueHandling = NullValueHandling.Ignore
    };
    
  2. JSON.NET can also handle Dictionary(string, object) very well. Create a more dynamic model and map it correctly. This Dictionary is only the resulting Model for the WebAPI, you should implement any logic for it. You also need some good mapping logic, which can be implemented with reflection.

I would use a convention where you create some mapping logic automatically for each property and you override this for properties which are dependent on security rules, e.g.

  ModelMapper.CreateByConvention<Product>()
     .Map(x => x.Created)
          .Never()
     .Map(x => x.UserName)
          .WhenUserInRole(Roles.Administrator)
     .Map(x => x.FirstName)
          .WhenUser(u => u.CanSeeFirstName());

5 Comments

1. Default for int is zero. And, it will be stripped from result 'cause it is default value. But, if it was an actual data, that was allowed to client?
2. Dictionaries isn't my solution too because it is to small to suite my needs
What do you mean by "Too Small"?
imagine that I have class TransactionDetail in which there is about 40 properties. And, my model returns a list of about 5000 such classes. And, I must exclude undesired/unallowed properties from it, at runtime, without knowing beforehand which one to exclude. Dictionaries? No, thanks.
It is only a question of a good mapping logic, see me updated answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.