json-api-dotnet/JsonApiDotNetCore

Attempting to setup sample app with filtering and getting error on filtered call.

edwardmarbry opened this issue · 3 comments

SUMMARY

Trying to use filters with EF Core and receiving error

DETAILS

Trying to use filters with EF Core and just following the getting started example and using my own models with a DB first EF Core setup. Googling I havent been able to find anything to points me in the direction of a solution.

Model snippet

[Resource]
public partial class Provider : Identifiable<long>
{

    [Attr(Capabilities = AttrCapabilities.AllowFilter | AttrCapabilities.AllowSort | AttrCapabilities.AllowView)]
    public string? FirstName { get; set; }

    [Attr(Capabilities = AttrCapabilities.AllowFilter | AttrCapabilities.AllowSort | AttrCapabilities.AllowView)]
    public string? MiddleName { get; set; }

    [Attr]
    public string? LastName { get; set; }

    [Attr(Capabilities = AttrCapabilities.AllowFilter | AttrCapabilities.AllowSort | AttrCapabilities.AllowView)]
    public int NPI { get; set; }
}

program.cs

builder.Services.AddDbContext<ClientDBContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("ClientDBContext"));
    options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});

builder.Services.AddJsonApi<ClientDBContext>(options =>
{
    options.Namespace = "jsonapi";
    options.UseRelativeLinks = true;
    options.IncludeTotalResourceCount = true;
    
    options.IncludeExceptionStackTraceInErrors = true;
    options.IncludeRequestBodyInErrors = true;
    options.SerializerOptions.WriteIndented = true;

});

var app = builder.Build();

app.UseRouting();

// Add JsonApiDotNetCore middleware.
app.UseJsonApi();

app.MapControllers();

app.Run();

``

STEPS TO REPRODUCE

Making a get call to http://localhost/jsonapi/providers returns correctly.

Making a get call to http://localhost/jsonapi/providers?filter[npi]=1111111111

returns

{
  "links": {
    "self": "/jsonapi/providers?filter[npi]=11111111111"
  },
  "errors": [
    {
      "id": "f860015b-2dc1-46ff-a26e-11ae5ccee664",
      "status": "400",
      "title": "The specified filter is invalid.",
      "detail": "Field chain on resource type 'providers' failed to match the pattern: zero or more relationships, followed by a to-many relationship. Relationship on resource type 'providers' expected. Failed at position 8: filter[^npi]",
      "source": {
        "parameter": "filter[npi]"
      },
      "meta": {
        "stackTrace": [
          "JsonApiDotNetCore.Errors.InvalidQueryStringParameterException: Exception of type 'JsonApiDotNetCore.Errors.InvalidQueryStringParameterException' was thrown.",
          " ---> JsonApiDotNetCore.Queries.Parsing.QueryParseException: Field chain on resource type 'providers' failed to match the pattern: zero or more relationships, followed by a to-many relationship. Relationship on resource type 'providers' expected.",
          "   at ResourceFieldChainExpression JsonApiDotNetCore.Queries.Parsing.QueryExpressionParser.ParseFieldChain(FieldChainPattern pattern, FieldChainPatternMatchOptions options, ResourceType resourceType, string alternativeErrorMessage) in /_/src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs:line 71",
          "   at QueryStringParameterScopeExpression JsonApiDotNetCore.Queries.Parsing.QueryStringParameterScopeParser.ParseQueryStringParameterScope(ResourceType resourceType, FieldChainPattern pattern, FieldChainPatternMatchOptions options) in /_/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs:line 43",
          "   at QueryStringParameterScopeExpression JsonApiDotNetCore.Queries.Parsing.QueryStringParameterScopeParser.Parse(string source, ResourceType resourceType, FieldChainPattern pattern, FieldChainPatternMatchOptions options) in /_/src/JsonApiDotNetCore/Queries/Parsing/QueryStringParameterScopeParser.cs:line 20",
          "   at ResourceFieldChainExpression JsonApiDotNetCore.QueryStrings.FilterQueryStringParameterReader.GetScope(string parameterName) in /_/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs:line 118",
          "   at void JsonApiDotNetCore.QueryStrings.FilterQueryStringParameterReader.ReadSingleValue(string parameterName, string parameterValue) in /_/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs:line 100",
          "   --- End of inner exception stack trace ---",
          "   at void JsonApiDotNetCore.QueryStrings.FilterQueryStringParameterReader.ReadSingleValue(string parameterName, string parameterValue) in /_/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs:line 112",
          "   at void JsonApiDotNetCore.QueryStrings.FilterQueryStringParameterReader.Read(string parameterName, StringValues parameterValue) in /_/src/JsonApiDotNetCore/QueryStrings/FilterQueryStringParameterReader.cs:line 64",
          "   at void JsonApiDotNetCore.QueryStrings.QueryStringReader.ReadAll(DisableQueryStringAttribute disableQueryStringAttribute) in /_/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs:line 60",
          "   at async Task JsonApiDotNetCore.Middleware.AsyncQueryStringActionFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) in /_/src/JsonApiDotNetCore/Middleware/AsyncQueryStringActionFilter.cs:line 29",
          "   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()+Awaited(?)",
          "   at void Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)",
          "   at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)",
          "   at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()",
          "   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextExceptionFilterAsync()+Awaited(?)"
        ]
      }
    }
  ]
}

VERSIONS USED

  • JsonApiDotNetCore version: 5.5.`
  • ASP.NET Core version: 8
  • Entity Framework Core version: 8.0.3
  • Database provider: Azure Sql

Your setup looks fine, but the filter used in the request is invalid. See https://www.jsonapi.net/usage/reading/filtering.html.

Oh my... Sorry what a waste of your time. I have been hitting drupal cms jsonapis for the past few months and they use that syntax, didnt know it wasnt standard.

Thanks !

No problem. There's no official standard for filtering in JSON:API. You can still use what you're familiar with by setting options.EnableLegacyFilterNotation, although its capabilities are quite limited.