Search code examples
c#.net-coreasp.net-apicontroller

How to load fields in a OneToMany relation?


How to load a OnetoMany Field when loading through APIController.

I have an Article model

public class Article : BaseEntity
{

    public string Title
    {
        get; set;
    }

    public Edition Edition
    {
        get; set;
    }

}

And an Edition model

public class Edition : BaseEntity
{
    public string Title
    {
        get; set;
    }

    public int Position { get; set; }

}

The BaseEntity model looks like that:

public class BaseEntity
{
    public Guid ID { get; set; }

    [Timestamp]
    public byte[] Timestamp { get; set; }

    public BaseEntity()
    {
        ID = Guid.NewGuid();
    }
}

I defined an HttpGet function in my Articles Controller, where I want to load all my articles.

[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesDefaultResponseType]
public ActionResult<IEnumerable<Article>> GetArticles([FromRoute] Guid editionId)
{
    return Ok(_context.Articles);
}

Unfortunately the EditionId is not loaded with the other fields. Here is what the JSON looks like:

[
    {
        "title": "Article Postman",
        "edition": null,
        "id": "74b53ba7-75a4-46c6-a70f-470e73c83ee5",
        "timestamp": "AAAAAAAAB+M="
    },
    {
        "title": "Title",
        "edition": null,
        "id": "d74b4ac3-7ddc-4c89-bd74-4fbe3fbe0cd8",
        "timestamp": "AAAAAAAAB+E="
    },
    {
        "title": "Article Postman 2",
        "edition": null,
        "id": "5dddd99f-151a-4325-91f7-c8295b872410",
        "timestamp": "AAAAAAAAB+U="
    }
]

Solution

  • I would suggest going for the simple solution that EF Core offers that is every time you call you data access layer for a specif data you add the .Include(x=>x.ReferenceIWantToLoad). This avoids any restructure in the project models to add the keyword 'virtual' to every Foreign Reference, example:

    var allArticlesWithEditions = await _dbContext.Articles.Include(x=>x.Edition).ToListAsync();
    

    PS: to be able to ignore infinite loop of references you want to add this to your startup file configuration :

    services.AddMvc()
            .AddJsonOptions(
                options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            );