Skip to main content

I made a custom endpoint:
 

 

I added the PrimaryQuote action:
 

 

I send a POST request to set a Sales Quote as primary:
 

 

I get a server error:
 

{

    "message": "An error has occurred.",

    "exceptionMessage": "Object reference not set to an instance of an object.",

    "exceptionType": "System.NullReferenceException",

    "stackTrace": "   at PX.Api.ContractBased.EntityService.Invoke(ISystemContract systemContract, String version, String name, EntityImpl entity, ActionImpl action, CbOperationContext operationContext, Boolean throwOnError)\r\n   at PX.Api.ContractBased.AspNetCore.CbEndpointFeatureServiceExtensions.Invoke(IEntityService entityService, ICbEndpointFeature feature, EntityImpl entity, ActionImpl action, CbOperationContext operationContext)\r\n   at PX.Api.ContractBased.WebApi.Controllers.ActionController.InvokeAction(String objectName, String actionName, ActionInvocation invocation)\r\n   at lambda_method(Closure , Object , ObjectA] )\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Objectt] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()"

}

 

I’m not sure what to try next with such a general error… can anyone confirm my steps are correct at least? I have found the behavior on Sales Quotes especially through the REST API can be somewhat unexpected because of the overlap with Opportunities.

I also tried adding the same PrimaryQuote action to the Opportunity entity in and extension of the Default endpoint:
 

 

{

    "message": "An error has occurred.",

    "exceptionMessage": "Operation failed",

    "exceptionType": "PX.Data.PXInvalidOperationException",

    "stackTrace": "   at PX.Api.ContractBased.EntityService.Invoke(ISystemContract systemContract, String version, String name, EntityImpl entity, ActionImpl action, CbOperationContext operationContext, Boolean throwOnError)\r\n   at PX.Api.ContractBased.AspNetCore.CbEndpointFeatureServiceExtensions.Invoke(IEntityService entityService, ICbEndpointFeature feature, EntityImpl entity, ActionImpl action, CbOperationContext operationContext)\r\n   at PX.Api.ContractBased.WebApi.Controllers.ActionController.InvokeAction(String objectName, String actionName, ActionInvocation invocation)\r\n   at lambda_method(Closure , Object , Objectc] )\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Objectn] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()",

    "innerException": {

        "message": "An error has occurred.",

        "exceptionMessage": "Object reference not set to an instance of an object.",

        "exceptionType": "System.NullReferenceException",

        "stackTrace": "   at PX.Objects.CR.OpportunityMaint.<PrimaryQuote>d__70.MoveNext()\r\n   at PX.Data.PXAction`1.<Press>d__39.MoveNext()\r\n   at PX.Data.PXAction`1.<Press>d__39.MoveNext()\r\n   at PX.Api.SyImportProcessor.SyStep.PressButton(PXAction button, PXAdapter adapter, SyView view, String actionName, Objecte] currents)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChangesInt(Object itemToBypass, PXFilterRowt] targetConditions, PXFilterRowr] filtersForAction, SyImportRowResult importResult)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object& itemToBypass, PXFilterRowN] targetConditions, PXFilterRowo] filtersForAction)\r\n   at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable(CancellationToken token)"

    }

}

I appreciate any help anyone can offer; there is a lot to know about the intricacies of this process.

Hi @PBSA ,

Are you testing the endpoint with a custom screen or a default screen? Could you please share a screenshot of the screen to show how the action was created?


Hi @PBSA,

I would recommend using default endpoint or extend the default endpoint to customize it. Is there any specific reason to create a new custom endpoint? 


@jinin It points to the default Sales Quote screen CR304500:

@Vignesh Ponnusamy I believe there is no default endpoint for Sales Quotes. Per your suggestion I did try adding a SalesQuote entity to a new extended default endpoint:
 

Here is the result from Postman:

{

    "message": "An error has occurred.",

    "exceptionMessage": "Object reference not set to an instance of an object.",

    "exceptionType": "System.NullReferenceException",

    "stackTrace": "   at PX.Api.ContractBased.EntityService.Invoke(ISystemContract systemContract, String version, String name, EntityImpl entity, ActionImpl action, CbOperationContext operationContext, Boolean throwOnError)\r\n   at PX.Api.ContractBased.AspNetCore.CbEndpointFeatureServiceExtensions.Invoke(IEntityService entityService, ICbEndpointFeature feature, EntityImpl entity, ActionImpl action, CbOperationContext operationContext)\r\n   at PX.Api.ContractBased.WebApi.Controllers.ActionController.InvokeAction(String objectName, String actionName, ActionInvocation invocation)\r\n   at lambda_method(Closure , Object , Objecti] )\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, ObjectI] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()"

}


I tried the same request I just posted (just clicked Send again in Postman, no changes anywhere) and got a diffferent error:

{

    "message": "An error has occurred.",

    "exceptionMessage": "Operation failed",

    "exceptionType": "PX.Data.PXInvalidOperationException",

    "stackTrace": "   at PX.Api.ContractBased.EntityService.Invoke(ISystemContract systemContract, String version, String name, EntityImpl entity, ActionImpl action, CbOperationContext operationContext, Boolean throwOnError)\r\n   at PX.Api.ContractBased.AspNetCore.CbEndpointFeatureServiceExtensions.Invoke(IEntityService entityService, ICbEndpointFeature feature, EntityImpl entity, ActionImpl action, CbOperationContext operationContext)\r\n   at PX.Api.ContractBased.WebApi.Controllers.ActionController.InvokeAction(String objectName, String actionName, ActionInvocation invocation)\r\n   at lambda_method(Closure , Object , Objectn] )\r\n   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Objectt] arguments)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__10.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()",

    "innerException": {

        "message": "An error has occurred.",

        "exceptionMessage": "The Set As Primary button is disabled.",

        "exceptionType": "PX.Data.PXActionDisabledException",

        "stackTrace": "   at PX.Data.PXAction`1.<Press>d__39.MoveNext()\r\n   at PX.Api.SyImportProcessor.SyStep.PressButton(PXAction button, PXAdapter adapter, SyView view, String actionName, Object] currents)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChangesInt(Object itemToBypass, PXFilterRowP] targetConditions, PXFilterRowP] filtersForAction, SyImportRowResult importResult)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object& itemToBypass, PXFilterRow.] targetConditions, PXFilterRow] filtersForAction)\r\n   at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable(CancellationToken token)"

    }

}

 

In the UI, I can see that Set As Primary is not disabled:

And when I click it in the UI, it does work (and the Set As Primary button does become disabled):

The Postman request continues to send the “Set As Primary button is disabled” error while this quote is already Primary. It returned that error for a while, but when I checked back, it returned to the initial error. I am beginning to think the problem is something to do with the keys I am sending in the body not being received correctly. Is there another way I should be sending them? You can see from the commented out “id” line I have tried sending the quote GUID without success. Should the keys instead be in the URL in some capacity?

 


Hi @PBSA ,

Could you please add the fields from the quote summary, as shown below, to the sales quote and try again?

 


@jinin I had some there already (key fields at least) but here I’ve added all the fields in the Quote Summary:
 

 

I can GET the quote using a url like: entity/Default_QuoteTest/23.200.001/SalesQuote/102272/1000001. I can also GET it with entity/Default_QuoteTest/23.200.001/SalesQuote/a8d6a130-25d5-4702-87cf-1ad24619a61f

But I still get the original error:

Thank you for suggesting. I’m sorry it still isn’t working.


Hi @PBSA ,

Please try the request below. I checked on my end, and it’s working fine for me.
 

Method: POST
URL: /entity/DefaultExtn/22.200.001/SalesQuote/PrimaryQuote
Request:
{

    "entity": {

        "OpportunityID": {

            "value": "OP000399"

        },

        "QuoteNbr": {

            "value": "Q000020"

        }

    }

}

 

 


@jinin Thank you so much for proving the problem was not with the endpoint - I do not have any working examples so did not know where to look. Given your example and help I was able to isolate an issue in a customization that allows manual quote numbers to be specified when they are sent via API:

protected override string GetNewNumberSymbol()
{
// Checks graph instance to determine if from API call
if(_Graph.IsContractBasedAPI)
{
// When AutoNumberAttribute NullMode is set to 'UserNumbering'
// And GetNewNumberSymbol() returns an empty string
// Attributes RowPersisting event will not override field with AutoNumber value
NullMode = NullNumberingMode.UserNumbering;
// when this is base.NullString I get System.NullReferenceException trying to set quote as primary via API - PBSA
//return base.NullString;
return null;
}
return base.GetNewNumberSymbol();
}

After commenting out the return base.NullString line and replacing it with the return null line, I was able to make quotes primary via REST API. I would never have found this issue without your help, thank you!


Reply