1

I need to use OData for my API endpoints in ASP.NET Core application, but all examples are about working directly with Data Model classes. In my application architecture I has service layer, methods of this service return DTO classes and then map to API view classes.

My data class (infrastructure layer):

public partial class Carrier : BaseEntity
{
    public string Name { get; set; }
    public string Code { get; set; }
    public string UsDotNumber { get; set; }
    public string McNumber { get; set; }

My DTO class:

public class CarrierBaseDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }
    public string Fein { get; set; }
    public string McNumber { get; set; }

My presentation (API) class:

public class CarrierAPI
{
    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }
    [JsonProperty(PropertyName = "code")]
    public string Code { get; set; }
    [JsonProperty(PropertyName = "fein")]
    public string Fein { get; set; }
    [JsonProperty(PropertyName = "mcNumber")]
    public string McNumber { get; set; }

my service method:

    public List<CarrierBaseDto> SearchCarriersDto()
    {
        var query = _context.Carriers
            .Where(c => !c.Deleted);

        IQueryable<CarrierBaseDto> queryDto = query.ProjectTo<CarrierBaseDto>(_mapperConfig);
        return queryDto.ToList();
    }

My controller method:

    [HttpGet]
    [Route("GetAll")]
    public IActionResult GetAll()
    {
        var carriers = _carrierService.SearchCarriersDto();
        var carriersApi = _mapper.Map<List<CarrierElementAPI>>(carriers);
        return new OkObjectResult(carriersApi);
    }

I want to add abilities to use $orderBy, $filter, $fields params. How to add it to my current architecture?

0

1 Answer 1

1

I think it was when they originally designed OData it was not intended to be used without DDD, because the metadata was suppose to allow you to handle the filter etc, which is now creating somewhat of a limitation on using it.

There's some hacky workarounds but they only partially work. The closest thing that I can think of that you can do is generically take in query options and apply them, Then use automapper to project to your queryable,

The only issue is the mappings from Entity to DTO in your automapper setup cannot be complex and must be setup through expression mapping

public Object[] Get(ODataQueryOptions<ProductDTO> options)
{
    ODataQuerySettings settings = new ODataQuerySettings()
    {
        PageSize = 5
    };

    IQueryable results = options.ApplyTo(_products.AsQueryable().ProjectTo<ProductDTO>(), settings);

    results.ToArray()
}
Sign up to request clarification or add additional context in comments.

5 Comments

but then how to implement it with $fields parameter, for example?
You can/can't, You can return an Object[], but if you're filtering fields your technically not returning the DTO.
@OlegSh I tried to go down this path originally eventually I just said screw it and decided to only operate on the entity. This is the closest you can get to what you want but it has its own limitation. If I've answered your question please mark as complete
but really sometimes Data Entity class can be unable to return via API because it can have virtual properties etc...
Yes, but those are the only few options, either make your data conform to the api or make your api conform to the data. Or you can implement your own dynamic filters

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.