Skip to content

After enabling options.EnableResourceHooks = true; I get a NullReference on GET Articles/GetSecondary [id/relationshipName] #924

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
woofi7 opened this issue Jan 18, 2021 · 11 comments · Fixed by #926 or #938
Assignees

Comments

@woofi7
Copy link

woofi7 commented Jan 18, 2021

DESCRIPTION

The request is crashing on this line because the type is IIdentifiable instead of the implemented type Image.
https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Configuration/ResourceGraph.cs#L85

The implementation seems to be lost at this place:
https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Hooks/Internal/ResourceHookExecutorFacade.cs#L131

System.NullReferenceException: Object reference not set to an instance of an object.
  at JsonApiDotNetCore.Configuration.ResourceGraph.GetRelationships
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Configuration\ResourceGraph.cs:85
  at JsonApiDotNetCore.Hooks.Internal.Traversal.TraversalHelper.RegisterRelationshipProxies
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Hooks\Internal\Traversal\TraversalHelper.cs:200
  at JsonApiDotNetCore.Hooks.Internal.Traversal.TraversalHelper.CreateRootNode
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Hooks\Internal\Traversal\TraversalHelper.cs:56
  at JsonApiDotNetCore.Hooks.Internal.ResourceHookExecutor.GetHook
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Hooks\Internal\ResourceHookExecutor.cs:199
  at JsonApiDotNetCore.Hooks.Internal.ResourceHookExecutor.OnReturn
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Hooks\Internal\ResourceHookExecutor.cs:121
  at JsonApiDotNetCore.Hooks.Internal.ResourceHookExecutorFacade.OnReturnRelationship
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Hooks\Internal\ResourceHookExecutorFacade.cs:131
  at JsonApiDotNetCore.Services.JsonApiResourceService`2+<GetSecondaryAsync>d__11.MoveNext
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Services\JsonApiResourceService.cs:137
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult
  at JsonApiDotNetCore.Controllers.BaseJsonApiController`2+<GetSecondaryAsync>d__17.MoveNext
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Controllers\BaseJsonApiController.cs:131
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult
  at JsonApiDotNetCore.Controllers.JsonApiController`2+<GetSecondaryAsync>d__4.MoveNext
    C:\projects\jsonapidotnetcore\src\JsonApiDotNetCore\Controllers\JsonApiController.cs:65
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult
  at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor+<Execute>d__0.MoveNext
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Threading.Tasks.ValueTask`1.get_Result
  at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult
  at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker+<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult
  at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker+<<InvokeNextActionFilterAsync>g__Awaited|10_0>d.MoveNext
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow
  at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next
  at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker+<<InvokeInnerFilterAsync>g__Awaited|13_0>d.MoveNext
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult
  at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker+<<InvokeNextExceptionFilterAsync>g__Awaited|25_0>d.MoveNext

VERSIONS USED

  • JsonApiDotNetCore version: 4.0.1
  • ASP.NET Core version: 5.0
  • Entity Framework Core version: 5.0
  • Database provider: Pomelo.Mysql
@bart-degreed
Copy link
Contributor

Fixed in https://github.com/json-api-dotnet/JsonApiDotNetCore/releases/tag/v4.0.2.

@woofi7
Copy link
Author

woofi7 commented Jan 20, 2021

@bart-degreed
The bug is still present.
During the execution, I enter the second if which put the resource on IIdentifiable

The relation between my 2 resources is a HasOne -> image is IIdentifiable.

public object OnReturnRelationship(object resourceOrResources)
{
    if (resourceOrResources is IEnumerable)
    {
        dynamic resources = resourceOrResources;
        return _resourceHookExecutor.OnReturn(resources, ResourcePipeline.GetRelationship).ToArray();
    }


    // This block
    if (resourceOrResources is IIdentifiable identifiable)
    {
        var resources = ToList(identifiable);
        return _resourceHookExecutor.OnReturn(resources, ResourcePipeline.GetRelationship).Single();
    }

    return resourceOrResources;
}

@woofi7
Copy link
Author

woofi7 commented Jan 22, 2021

@maurei
I have another problem, this time with the enumerable resources.

The relation is a OneToMany. When getting the secondary relation I get this error:
http://localhost:5000/api/v1/authors/8/social-links
'System.Collections.Generic.HashSet<LagendaBackend.Data.Models.SocialLink>' does not contain a definition for 'ToArray'

This error is from the first if in the same function as before.
https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Hooks/Internal/ResourceHookExecutorFacade.cs#L125

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.Generic.HashSet<LagendaBackend.Data.Models.SocialLink>' does not contain a definition for 'ToArray'
  at CallSite.Target
  at JsonApiDotNetCore.Hooks.Internal.ResourceHookExecutorFacade.OnReturnRelationship
    D:\workspace\JsonApiDotNetCore\src\JsonApiDotNetCore\Hooks\Internal\ResourceHookExecutorFacade.cs:126
  at JsonApiDotNetCore.Services.JsonApiResourceService`2+<GetSecondaryAsync>d__11.MoveNext
    D:\workspace\JsonApiDotNetCore\src\JsonApiDotNetCore\Services\JsonApiResourceService.cs:137

@farturi
Copy link

farturi commented Jan 27, 2021

I just wrote a fix:
#932

@maurei
Copy link
Member

maurei commented Jan 27, 2021

@farturi I'll be looking into this issue tomorrow. Thanks for digging deep into it!

@maurei
Copy link
Member

maurei commented Feb 1, 2021

@farturi I have been unable to reproduce the issue.

The relation is a OneToMany. When getting the secondary relation I get this error:
http://localhost:5000/api/v1/authors/8/social-links

The scenario of one to many of this particular hook is covered in this test. Can you provide us with a repro example?

@bart-degreed
Copy link
Contributor

@maurei change Author.Articles from IList to ISet and the test you linked to fails with the error mentioned:


Xunit.Sdk.TrueException
/api/v1/authors/1/articles returned InternalServerError status code with body: {"errors":[{"id":"37439262-ed5f-4f3c-afcc-caae7a5fb4ad","status":"500","title":"An unhandled error occurred while processing this request.","detail":"'System.Collections.Generic.HashSet<JsonApiDotNetCoreExample.Models.Article>' does not contain a definition for 'ToArray'","meta":{"stackTrace":["Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.Generic.HashSet<JsonApiDotNetCoreExample.Models.Article>' does not contain a definition for 'ToArray'\r","   at object CallSite.Target(Closure, CallSite, object)\r","   at TRet System.Dynamic.UpdateDelegates.UpdateAndExecute1<T0, TRet>(CallSite site, T0 arg0)\r","   at object JsonApiDotNetCore.Hooks.Internal.ResourceHookExecutorFacade.OnReturnRelationship(object resourceOrResources) in D:/Source/Repos/JsonApiDotNetCore/src/JsonApiDotNetCore/Hooks/Internal/ResourceHookExecutorFacade.cs:line 125\r","   at async Task<object> JsonApiDotNetCore.Services.JsonApiResourceService<TResource, TId>.GetSecondaryAsync(TId id, string relationshipName, CancellationToken cancellationToken) in D:/Source/Repos/JsonApiDotNetCore/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs:line 137\r","   at async Task<IActionResult> JsonApiDotNetCore.Controllers.BaseJsonApiController<TResource, TId>.GetSecondaryAsync(TId id, string relationshipName, CancellationToken cancellationToken) in D:/Source/Repos/JsonApiDotNetCore/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 131\r","   at async Task<IActionResult> JsonApiDotNetCore.Controllers.JsonApiController<TResource, TId>.GetSecondaryAsync(TId id, string relationshipName, CancellationToken cancellationToken) in D:/Source/Repos/JsonApiDotNetCore/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 65\r","   at async ValueTask<IActionResult> Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)\r","   at TResult System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()\r","   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()+Awaited(?)\r","   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()+Awaited(?)\r","   at void Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)\r","   at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)\r","   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()+Awaited(?)\r","   at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextExceptionFilterAsync()+Awaited(?)"]}}]}
Expected: True
Actual:   False
   at JsonApiDotNetCoreExampleTests.Acceptance.ResourceDefinitionTests.Article_Through_Secondary_Endpoint_Is_Hidden() in D:\Source\Repos\JsonApiDotNetCore\test\JsonApiDotNetCoreExampleTests\Acceptance\ResourceDefinitions\ResourceDefinitionTests.cs:line 240
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass48_1.<<InvokeTestMethodAsync>b__1>d.MoveNext() in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\Runners\TestInvoker.cs:line 264
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in C:\Dev\xunit\xunit\src\xunit.core\Sdk\ExceptionAggregator.cs:line 90

@woofi7
Copy link
Author

woofi7 commented Feb 2, 2021

@maurei
I've pushed my repo to github in private. I've invited you as a collaborator to this repo!

@woofi7
Copy link
Author

woofi7 commented Feb 2, 2021

@maurei
I have tried to do the same fix as you have done for the SingleOrDefault for the ToArray at the line 125 and it seems to work In this situation!

https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Hooks/Internal/ResourceHookExecutorFacade.cs#L125
Become:
return Enumerable.ToArray(_resourceHookExecutor.OnReturn(resources, ResourcePipeline.GetRelationship));

@maurei
Copy link
Member

maurei commented Feb 3, 2021

Thank you. I suspected that Enumerable.ToArray was going to fix the problem, but I held it off because I wasn't sure where it originated from. Fixed in #938

@bart-degreed
Copy link
Contributor

Fixes for these issues are in https://github.com/json-api-dotnet/JsonApiDotNetCore/releases/tag/v4.0.3. Thanks @woofi7, @farturi and @manuelTscholl for helping out on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants