Daniel Clark
Daniel Clark

Reputation: 615

Excluding/including navigation properties

I have the following entity class which contains two scalar property and two navigational property

public class Artist
{
    public int Id { get; set; }

    public string Name { get; set; }

    public ICollection<ArtistGenre> ArtistGenres { get; set; }

    public ICollection<ArtistImage> ArtistImages { get; set; }
}

Just for this example I would call the entity context inside the controller with

using (var revrbContext = new RevrbContext())
{
    var response = revrbContext.Artists.Find(1);

    return Request.CreateResponse(HttpStatusCode.OK, response);
}

And the response data will indeed look like this

{"Id":1,"Name":"Test","ArtistGenres":null,"ArtistImages":null}

My question is, how would I go about excluding the navigation properties from the response string yet I would like to still be able to include the navigation properties when they are either not null or are required.

Ideally I would like to do something like this to include the navigation properties

http://somewebsite.com/api/artist?id=1&bucket=genres&bucket=images

However if the URL were to not continue any bucket parameters then the response should not contain any the respective navigation properties.

Update

I have figured a way to omit properties by mapping the result to an anonymous type (I could use DTO as well), but still haven't been able to figure out a clean way to include navigation properties when they are required

Mapping an entity type and a single navigation property to an anonymous type:

var response =
await
revrbContext.Artists.Include("ArtistGenres.Genre")
            .Where(artist => artist.Id == 1)
            .Select(artist => new
                {
                    artist.Id,
                    Genre = artist.ArtistGenres.Select(
                                        article => new {article.Genre.Name})
                }).FirstOrDefaultAsync();

However, if I wanted to include multiple navigation properties I could have something like this:

if (bucket.Contains("images") && bucket.Contains("genres"))
{
    var response =
        await
        revrbContext.Artists.Include("ArtistArticles.Article")
                                .Include("ArtistImages.Image")
                                ...etc
}

if (bucket.Contains("images"))
{
    var response =
        await
        revrbContext.Artists.Include("ArtistImages.Image")
                            ...etc
}

As you can see, the code starts to get repetitive and messy. I am hoping for a way to chain on navigation properties explicitly whether they have been requested for or not before the query is executed.

Upvotes: 2

Views: 3086

Answers (1)

Brian Rogers
Brian Rogers

Reputation: 129687

Asp.Net Web API uses Json.Net behind the scenes to do the JSON serialization. This being the case, you can set the serializer to ignore null property values. In other words, when the value of a property is null, it will not be present in the output.

To do this, add the following line to the WebApiConfig.cs file in the App_Start folder:

config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = 
    Newtonsoft.Json.NullValueHandling.Ignore;

You can then use the URL parameters in your method as you suggested to determine whether to set those property values on your object and thus selectively include them in the response.

Upvotes: 2

Related Questions