I am currently trying to set up a Non-Entity Framework environment to access data via REST/JSON:API in ASP.NET Core 3.1 with https://github.com/json-api-dotnet/JsonApiDotNetCore
I followed the example as shown in: https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/Examples/NoEntityFrameworkExample/Services/WorkItemService.cs
So here is my sample method:
public class DepartmentResourceService : IResourceService<Department>
{
public Task<IReadOnlyCollection<Department>> GetAsync(CancellationToken cancellationToken)
{
IReadOnlyCollection<Department> departments = new List<Department>{
new Department{ Id = 1, Name = "SE", Contact = "se@someaddress.at" },
new Department{ Id = 2, Name = "SD", Contact = "sd@someaddress.at" }
}.AsReadOnly();
return Task.FromResult(departments);
}
...
}
My example works pretty well, but I haven't figured out how I can access the given JSON:API fields-filter. However: The filters do apply automatically somehow and only the given fields are sent which were defined in the query string, but the filter is applied after the object was generated. When using EF, I can see that the sql-queries are already limited to the defined JSON:API fields-filter list, therefore the object is only filled up with informationen that was requested and nothing else.
I would like to do the same without EF, but I am missing that filter information in order to do so.
I could figure out, that there is an Interface called ITargetedFields
(https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Resources/TargetedFields.cs/) and I thought maybe this could be injected into the constructor like so:
public class DepartmentResourceService : IResourceService<Department>
{
private readonly ITargetedFields targetedFields;
public DepartmentResourceService(ITargetedFields targetedFields)
{
this.targetedFields = targetedFields;
}
...
}
But the properties Attributes
and Relationships
Collections of ITargetedFields
are always zero-length.
I couldn't find something in the docs or examples.
Any ideas?
I finally found a way, how to access query information, such as fields, pagination, includes in IResourceService<TResource>
:
There are several IQueryConstraintProvider
service providers registered in JsonApiApplicationBuilder
in the method AddQueryStringLayer()
with a Scope-Lifetime:
IIncludeQueryStringParameterReader
IFilterQueryStringParameterReader
ISortQueryStringParameterReader
ISparseFieldSetQueryStringParameterReader
IPaginationQueryStringParameterReader
IResourceDefinitionQueryableParameterReader
They are injected by DI in the constructor of your IResourceService<TResource>
implementation, here is an example:
public class DepartmentResourceService : IResourceService<Department>
{
private readonly ISparseFieldSetQueryStringParameterReader _sparseFieldSetQueryStringParameterReader;
private readonly IIncludeQueryStringParameterReader _includeQueryStringParameterReader;
private readonly ISortQueryStringParameterReader _sortQueryStringParameterReader;
private readonly IPaginationQueryStringParameterReader _paginationQueryStringParameterReader;
public DepartmentResourceService(
ISparseFieldSetQueryStringParameterReader sparseFieldSetQueryStringParameterReader,
IIncludeQueryStringParameterReader includeQueryStringParameterReader,
ISortQueryStringParameterReader sortQueryStringParameterReader,
IPaginationQueryStringParameterReader paginationQueryStringParameterReader
)
{
_sparseFieldSetQueryStringParameterReader = sparseFieldSetQueryStringParameterReader;
_includeQueryStringParameterReader = includeQueryStringParameterReader;
_sortQueryStringParameterReader = sortQueryStringParameterReader;
_paginationQueryStringParameterReader = paginationQueryStringParameterReader;
}
public Task<IReadOnlyCollection<Department>> GetAsync(CancellationToken cancellationToken)
{
// Accessing all provided information:
IReadOnlyCollection<ExpressionInScope> constraints = _sparseFieldSetQueryStringParameterReader.GetConstraints();
IReadOnlyCollection<ExpressionInScope> includes = _includeQueryStringParameterReader.GetConstraints();
IReadOnlyCollection<ExpressionInScope> sortQuery = _sortQueryStringParameterReader.GetConstraints();
IReadOnlyCollection<ExpressionInScope> pagination = _paginationQueryStringParameterReader.GetConstraints();
// ***************************************************************
// Do what ever you need to do, with the information provided here
// ***************************************************************
// Return something
IReadOnlyCollection<Department> departments = new List<Department>{
new Department{ Id = 1, Name = "SE", Contact = "se@someaddress.at" },
new Department{ Id = 2, Name = "SD", Contact = "sd@someaddress.at" }
}.AsReadOnly();
return Task.FromResult(departments);
}
...
}