Search code examples
c#-4.0odatadto

Is it possible to use ODataQueryOptions with DTO's?


ContentType --> EF model

ContentTypes --> DTO

In my OData controller:

   public Task<IQueryable<ContentTypes>> Get(ODataQueryOptions<ContentTypes> options) 
   {
        var result = options.ApplyTo(_repository.Query().Get()
            .Where(u => u.UserId == userId)
            .OrderBy(o => o.Description))
            .Cast<ContentTypes>();

        return result;
   }

I get an error 500 when trying to apply the ODataQueryOptions. Since the class already inherits ODataController do I even need to do theoptions.ApplyTo(...)?


Solution

  • The solution for this was to ensure the return type is the the DTO's type, and that the ODataQueryOptions are applied to the EF entity. I then use Automapper to map the result to the DTO.

    I have updated the answer based on @Schandlich 's suggestions, however some issues persist:

        [Queryable]
        public virtual IHttpActionResult Get(ODataQueryOptions<ContentType> options)
        {
            var userId = 102;   // mock
    
            try
            {
                var results = options.ApplyTo(_uow.Repository<ContentType>()
                    .Query()
                    .Get()
                    .Include(u => u.User)
                    .Where(u => u.UserId == userId)
                    .OrderBy(o => o.Description)).Cast<ContentType>()
                    .Select(x => new ContentTypeDTO()
                    {
                        //projection goes here
                        ContentTypeId = x.ContentTypeId,
                        Description = x.Description,
                        UserDTO = new UserDTO 
                        { 
                            UserId = x.UserId,
                            UserName = x.User.UserName
                        }
                    });
    
                return this.Ok(results);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    

    The reason for using ODataQueryOptions is that I want EF to handle the filtering down at the database call level. Otherwise, I would get all records returned, then the Queryable would kick in to return, say the first page of results.

    I removed the Automapper code, but curious as to why not use this?

    As @Schandlich pointed out, however, this will not work for $select or $expand.