Search code examples
c#.netasp.net-web-api2odatarestier

RESTier PUT/PATCH not being called


currently i am working on a project with RESTier 1.0 NuGet-Package installed. I am using a custom model builder with some DTOs. To build the API i use Controllers that inherit from ODataController. Querying or posting data is no problem so far.

When i try to Update a record with a PATCH or PUT request, the corresponding controller actions are not being called, but instead i get Exceptions.

  1. First i did get ChangeSetPreparer is missing exceptions.
  2. After a change i did get null reference exceptions.

So to avoid the first i have added a ChangeSetInitializer and a SubmitExecutor that i have found in some Github-Source (that i cannot remember anymore):

public class ExternalApi : ApiBase
{
    public ExternalApi(IServiceProvider serviceProvider) : base(serviceProvider)
    {
    }

public static new IServiceCollection ConfigureApi(Type apiType, IServiceCollection services)
{
    return ApiBase.ConfigureApi(apiType, services)
    .AddService<IModelBuilder, CustomModelBuilder>()
    .AddService<IChangeSetInitializer, ChangeSetInitializer>()
    .AddService<ISubmitExecutor, SubmitExecutor>();
}

private class ChangeSetInitializer : IChangeSetInitializer
{
    public Task InitializeAsync(SubmitContext context, CancellationToken cancellationToken)
    {
        context.ChangeSet = new ChangeSet();
        return Task.FromResult<object>(null);
    }
}

private class SubmitExecutor : ISubmitExecutor
{
    public Task<SubmitResult> ExecuteSubmitAsync(SubmitContext context, CancellationToken cancellationToken)
    {
        return Task.FromResult(new SubmitResult(context.ChangeSet));
    }
}
}

After adding those, the first problem seems to be solved but instead i am getting null reference exceptions with the following stacktrace:

bei Microsoft.Restier.Publishers.OData.RestierController.CreateResult(Type resultType, Object result) bei Microsoft.Restier.Publishers.OData.RestierController.CreateUpdatedODataResult(Object entity) bei Microsoft.Restier.Publishers.OData.RestierController.d__3f.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei Microsoft.Restier.Publishers.OData.RestierController.d__20.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Threading.Tasks.TaskHelpersExtensions.d__3`1.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Web.Http.Controllers.ExceptionFilterResult.d__0.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Web.Http.Controllers.ExceptionFilterResult.d__0.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Web.Http.HttpServer.d__0.MoveNext()

These are examples for the action signatures that i use:

[EnableQuery]
public IQueryable<StoreDTO> Get()
[EnableQuery]
public SingleResult<StoreDTO> Get([FromODataUri] int key)
public async Task<IHttpActionResult> Post(StoreDTO store)
public async Task<IHttpActionResult> Put([FromODataUri] int key, StoreDTO store)
    public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<StoreDTO> store)

I tried diverse JSON-Objects that would match the DTO but i still get null reference exceptions even before the Put or Patch is being called.


Solution

  • I found a solution or at least a workaround. I changed my WebApiConfig a little bit.

    Instead of: MapRestierRoute(...) from Microsoft.Restier.Publishers.OData.HttpConfigurationExtensions i am using now: MapODataServiceRoute(...) from System.Web.OData.Extensions.HttpConfigurationExtensions