Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using partials and projections of entities in Web API

I am using breeze with Web API. I don't have a good grasp on how to "Filter columns" or how to not expose and entire table to my Web API. I am using the Entity Framework as my source, and both of my questions are addressed by John Papa here: http://www.johnpapa.net/spajs04/#comment-113761 and confirmed to be a good solution by Ward Bell below. Can someone please show me how I to use the entity framework to create a partial or projection that is queryable in my webapi and will work with breeze?

Here is my current function in the webapi

[HttpGet]
public IQueryable<Contact> GetContacts()
{
    return _contextProvider.Context.Contact;
}

Here is my current class:

public class Contact
{
    [Key]
    public Guid ID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string NickName { get; set; }
    public string JobTitle { get; set; }
    public DateTime BirthDate { get; set; }
    public bool Gender { get; set; }
    public string SSN { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateUpdated { get; set; }

    public virtual ICollection<Address> Address { get; set; }
}

I would like to have a queryable webapi function that is my current class WITHOUT the SSN field. A solution that works a "database first" entity and does not involve changing my database or adding "views" would be great.

like image 639
chris_dotnet Avatar asked Dec 21 '22 07:12

chris_dotnet


1 Answers

Client-side projection is fine when you're trying to reduce the payload. You need something server-side when you must ensure that certain data (e.g., SSN) are truly and safely hidden from the client.

@james suggestion - to use the [NonSerialized] (or JSON.NET's [JsonIgnore] attribute) - is an easy and effective approach when the SSN should never go to the client.

It's too inflexible if the SSN should be visible on the client in authorized circumstances (e.g., a user reviewing her own SSN or an HR person with the right to see the SSN). The JSON.NET IContractResolver gives you tremendous flexibility in deciding dynamically, based on authorization rules, what properties may cross the service boundary.

Some might consider addressing this problem with the serializer as too much of a hack. They might be satisfied by the server-side projection that you showed, @chris_dotnet. Btw, it still makes sense to return an IQueryable from the projection so that the client can reduce the network payload with a filtering query.

Others will prefer to define a DTO (ContactDTO) and serialize that over the wire.

[HttpGet]
    public IQueryable GetContacts()
    {
      return _contextProvider.Context.Contacts
        .Select(p =>
            new ContactDto
            {
                FirstName = p.FirstName,
                ID = p.ID,
                LastName = p.LastName
            });
    }

This IQueryable is more robust than the projection version because the filtering can take place on the data tier rather than the server tier.

On the client-side you can either define metadata for the ContactDto type or you can use a JsonResultsAdapter to map the ContactDto data into a Contact Breeze entity.

Using the JsonResultsAdapter presupposes that you actually want the Contact type - the type as it is shaped in the business model on the server - to be known on the client.

You may not want the server-side Contact shape to be exposed from your service. Many people feel really strongly about this. If you are one of those people, you're better off defining a "DTO Model" representing the entities as you want them to be seen on the client. That means learning to create metadata for your DTO model and writing mapping logic on the server to move between DTOs and your business model.

You can see how all of this can become a big topic. It's one that I'll be taking up soon in the Breeze documentation. Consider this answer a taste of things to come. The take-away is ... you have good choices for hiding data that users' shouldn't see.

like image 95
Ward Avatar answered Jan 21 '23 06:01

Ward