diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index bad0e19743..f868670ebd 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -190,7 +190,7 @@ Global
{6DFA30D7-1679-4333-9779-6FB678E48EF5}.Release|x64.ActiveCfg = Release|Any CPU
{6DFA30D7-1679-4333-9779-6FB678E48EF5}.Release|x64.Build.0 = Release|Any CPU
{6DFA30D7-1679-4333-9779-6FB678E48EF5}.Release|x86.ActiveCfg = Release|Any CPU
- {6DFA30D7-1679-4333-9779-6FB678E48EF5}.Release|x86.Build.0 = Release|Any CPU\
+ {6DFA30D7-1679-4333-9779-6FB678E48EF5}.Release|x86.Build.0 = Release|Any CPU
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -203,6 +203,7 @@ Global
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Release|x64.Build.0 = Release|Any CPU
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Release|x86.ActiveCfg = Release|Any CPU
{09C0C8D8-B721-4955-8889-55CB149C3B5C}.Release|x86.Build.0 = Release|Any CPU
+ {DF9BFD82-D937-4907-B0B4-64670417115F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
index fd3a8b48e8..854a962a9f 100644
--- a/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
+++ b/src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs
@@ -78,7 +78,8 @@ public DefaultEntityRepository(
_resourceDefinition = resourceDefinition;
}
- ///
+
+
public virtual IQueryable Get()
{
if (_jsonApiContext.QuerySet?.Fields != null && _jsonApiContext.QuerySet.Fields.Count > 0)
@@ -87,6 +88,18 @@ public virtual IQueryable Get()
return _dbSet;
}
+ ///
+ public virtual IQueryable GetQueryable()
+ => _dbSet;
+
+ public virtual IQueryable Select(IQueryable entities, List fields)
+ {
+ if (fields?.Count > 0)
+ return entities.Select(fields);
+
+ return entities;
+ }
+
///
public virtual IQueryable Filter(IQueryable entities, FilterQuery filterQuery)
{
@@ -127,7 +140,7 @@ public virtual IQueryable Sort(IQueryable entities, List
public virtual async Task GetAsync(TId id)
{
- return await Get().SingleOrDefaultAsync(e => e.Id.Equals(id));
+ return await GetQueryable().SingleOrDefaultAsync(e => e.Id.Equals(id));
}
///
@@ -135,7 +148,7 @@ public virtual async Task GetAndIncludeAsync(TId id, string relationshi
{
_logger?.LogDebug($"[JADN] GetAndIncludeAsync({id}, {relationshipName})");
- var includedSet = Include(Get(), relationshipName);
+ var includedSet = Include(GetQueryable(), relationshipName);
var result = await includedSet.SingleOrDefaultAsync(e => e.Id.Equals(id));
return result;
diff --git a/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs b/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
index f861ce10e2..ce23eb8ed2 100644
--- a/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
+++ b/src/JsonApiDotNetCore/Data/IEntityReadRepository.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -18,8 +19,16 @@ public interface IEntityReadRepository
/// The base GET query. This is a good place to apply rules that should affect all reads,
/// such as authorization of resources.
///
+ IQueryable GetQueryable();
+
+ [Obsolete("This method has been deprecated, use GetQueryable() instead")]
IQueryable Get();
+ ///
+ /// Apply fields to the provided queryable
+ ///
+ IQueryable Select(IQueryable entities,List fields);
+
///
/// Include a relationship in the query
///
diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
index 53cfc7a7c1..3fb01fa4be 100644
--- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs
+++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs
@@ -98,7 +98,7 @@ public virtual async Task DeleteAsync(TId id)
public virtual async Task> GetAsync()
{
- var entities = _entities.Get();
+ var entities = _entities.GetQueryable();
entities = ApplySortAndFilterQuery(entities);
@@ -108,6 +108,9 @@ public virtual async Task> GetAsync()
if (_jsonApiContext.Options.IncludeTotalRecordCount)
_jsonApiContext.PageManager.TotalRecords = await _entities.CountAsync(entities);
+ if (_jsonApiContext.QuerySet?.Fields?.Count > 0)
+ entities = _entities.Select(entities, _jsonApiContext.QuerySet.Fields);
+
// pagination should be done last since it will execute the query
var pagedEntities = await ApplyPageQueryAsync(entities);
return pagedEntities;
@@ -240,7 +243,7 @@ protected virtual IQueryable IncludeRelationships(IQueryable e
private async Task GetWithRelationshipsAsync(TId id)
{
- var query = _entities.Get().Where(e => e.Id.Equals(id));
+ var query = _entities.GetQueryable().Where(e => e.Id.Equals(id));
_jsonApiContext.QuerySet.IncludedRelationships.ForEach(r =>
{
diff --git a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs
index 15667c1872..6953b5f49c 100644
--- a/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs
+++ b/test/DiscoveryTests/ServiceDiscoveryFacadeTests.cs
@@ -1,4 +1,3 @@
-using System;
using GettingStarted.Models;
using GettingStarted.ResourceDefinitionExample;
using JsonApiDotNetCore.Builders;
@@ -7,7 +6,6 @@
using JsonApiDotNetCore.Models;
using JsonApiDotNetCore.Services;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
index 95ea814a5d..b161b14c87 100644
--- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs
@@ -61,5 +61,42 @@ public async Task Total_Record_Count_Included()
foreach(var item in deserializedBody)
Assert.Equal(person.Id, item.OwnerId);
}
+
+ [Fact]
+ public async Task Sparse_Fields_Works_With_Get_Override()
+ {
+ // arrange
+ var builder = new WebHostBuilder()
+ .UseStartup();
+ var server = new TestServer(builder);
+ var client = server.CreateClient();
+ var context = (AppDbContext)server.Host.Services.GetService(typeof(AppDbContext));
+ var jsonApiContext = (IJsonApiContext)server.Host.Services.GetService(typeof(IJsonApiContext));
+
+ var person = new Person();
+ context.People.Add(person);
+ var todoItem = new TodoItem();
+ todoItem.Owner = person;
+ context.TodoItems.Add(todoItem);
+ context.SaveChanges();
+
+ var authService = (IAuthorizationService)server.Host.Services.GetService(typeof(IAuthorizationService));
+ authService.CurrentUserId = person.Id;
+
+ var httpMethod = new HttpMethod("GET");
+ var route = $"/api/v1/todo-items/{todoItem.Id}?fields[todo-items]=description";
+
+ var request = new HttpRequestMessage(httpMethod, route);
+
+ // act
+ var response = await client.SendAsync(request);
+ var responseBody = await response.Content.ReadAsStringAsync();
+ var deserializedBody = _fixture.GetService().Deserialize(responseBody);
+
+ // assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(todoItem.Description, deserializedBody.Description);
+
+ }
}
}
diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
index 4ce5da35d8..2bf33346c4 100644
--- a/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
+++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Repositories/AuthorizedTodoItemsRepository.cs
@@ -23,9 +23,9 @@ public AuthorizedTodoItemsRepository(
_authService = authService;
}
- public override IQueryable Get()
+ public override IQueryable GetQueryable()
{
- return base.Get().Where(todoItem => todoItem.OwnerId == _authService.CurrentUserId);
+ return base.GetQueryable().Where(todoItem => todoItem.OwnerId == _authService.CurrentUserId);
}
}
}