Mart_
Mart_

Reputation: 36

ASP.net Core: Populating OData properties on the filtered list as IQueryable

I have a fully working OData API which is returning the right responses for all of my domain objects, which is great. The part I'm struggling with is how to populate objects with values that are not entities.

I have a list of InventoryItems which has a list ReadingTags but when I try to iterate through the ReadingTags after converting to a list of DTOs it seems that I have access to the entire list of InventoryItems as the execution of the data has been deferred until I send the serialize the response to the user. The response from a third-party web service will then be merged into the DTO before being sent as the response.

What is the best way to do this? I've looked at middleware, and filters and I'm at a loss. For reference, here is my code:

Domain entities:

public class InventoryItem
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual ISet<ReadingTag> ReadingTags { get; set; } = new HashSet<ReadingTag>();
}

public class ReadingTag
{
    public virtual Guid Id { get; set; }
    public virtual string DeviceName { get; set; }
    // Can't add this to the domain as it's not a database/entity property
    //public IList<double> Readings { get; set; } = new List<double>();
}

DTO entities:

public class InventoryItemDto
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public IList<double> Readings { get; set; } = new List<double>();
}

Controller:

[HttpGet]
[EnableQuery]
[ProducesResponseType(200)]
public ActionResult Get()
{
    var query = applicationService.All();
    var results = _mapper.Map<List<InventoryItemDto>>(query); // Automapper
    return Ok(results);
}

Service:

public Task<IQueryable<InventoryItem>> All()
{
    var inventoryItems = _session.Query<InventoryItem>();
    // I want to be able to send the filtered response to another service to populate the Readings of the ReadingTags
    return inventoryItems;
}

Upvotes: 0

Views: 617

Answers (1)

Mart_
Mart_

Reputation: 36

It's fixed, I can now filter within the service and work with the DTO too, thank you for your help:

Install-Package AutoMapper.AspNetCore.OData.EFCore
[HttpGet]
[ProducesResponseType(200)]
public IActionResult Get(ODataQueryOptions<InventoryItem> options)
    {
    var results = _readingService.All(options);
    return Ok(results);
}
public IList<InventoryItemDto> All(ODataQueryOptions<InventoryItem> options)
{
    var query = _session.Query<InventoryItem>();
    var inventoryItems = query.GetQuery(_mapper, options); // Filter applied here!
    var results = _mapper.Map<List<InventoryItemDto>>(inventoryItems);
    // Removed for brevity
    return results;
}

Upvotes: 1

Related Questions