Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit objects in a collection from being serialized based on User

I have a webapi that returns an object that contains some collections of objects which also contains a collection of objects. Each of these objects has a bool that represents if the object is 'published' See classes below for general idea.

public class A {
  public int ID { get; set; }
  public List<B> b { get; set;}
}

public class B {
  public List<C> c { get; set; }
  public List<D> d { get; set; }
  public bool published { get; set; }
}

public class C {
  public string Title { get; set; }
  public bool published { get; set; }
}

public class D {
  public string Title { get; set; }
  public bool published { get; set; }
}

What is the best way to make it so when I serialize any of these objects that an unpublished child objects are not included if the user doesn't meet the requirements, IE not in a specific role. Can I add data attributes to my model in some way? I have had a look into using a custom IContractResolver but I'm not sure its the best way to handle the nested objects. Should I be handling this in the serializing stage or should I be removing the unpublished objects from the children after I get the object from the database.

like image 386
Declan Cook Avatar asked Jun 10 '14 17:06

Declan Cook


People also ask

How can we disallow serialization of variables?

You can prevent member variables from being serialized by marking them with the NonSerialized attribute as follows. If possible, make an object that could contain security-sensitive data nonserializable. If the object must be serialized, apply the NonSerialized attribute to specific fields that store sensitive data.

What are the types of serialization?

There are three types of serialization in . Net : Binary Serialization, SOAP Serialization and XML Serialization.

Why do we serialize objects in C#?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed.


2 Answers

As the comments (rightly) pointed out I was going about this in slightly the wrong way.

I solved my problems by having two database requests basic looks something like this.

A a = null;

if(User.IsInRole("Role")){
   a = db.A.Find(Id);
} else {
   a = (from a in db.A
        join b in db.B on a.ID equals b.ID
        join c in db.C on b.ID equals c.ID
        join d in db.D on b.ID equals d.ID
        where a.ID == id && b.Published && c.Published && d.Published
        select a);
}

if(a == null)
   return NotFound();

return Ok(a);

I was trying to avoid code like this but I'm not sure there is a better way to do it.

like image 137
Declan Cook Avatar answered Nov 02 '22 11:11

Declan Cook


Actually I would propose for a certain users to load only needed data as this will increase the performance. The case if you want to load all data (both published and unpublished) is trivial. For the user who may view only published items I would make such query:

A model = context.ACollection.Where(a => a.ID == id).Select(a => 
     new A { 
         ID = a.ID, 
         b = a.b.Where(i => i.published == true).Select(i => 
             new B{
                 published = true, 
                 c = i.c.Where(c_item => c_item.published == true),
                 d = i.d.Where(d_item => d_item.published == true)
             })
    }).Single();

This query should give you good performance.

like image 25
mr100 Avatar answered Nov 02 '22 09:11

mr100