Passing a View to a Function

Is there a way to pass a DataView to a function from App Studio?
If have a runtime view called MemoView that displays a list of stuff (rows/columns).
On a button click, I would like to send that whole view in its current state to my function as a DataSet in order to do more processing.

I created an IN parameter that was of type DataSet, but it gave me this when I passed it in from App Studio:

Newtonsoft.Json.JsonSerializationException: Unexpected JSON token when reading DataTable. Expected StartArray, got String. Path 'UD34View'.
   at Newtonsoft.Json.Converters.DataTableConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Converters.DataSetConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
   at Epicor.Functions.FunctionRestAdapter`2.Run(IFunctionRestHost host, JObject input) in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionRestAdapter.cs:line 42
   at Epicor.RESTApi.Functions.Controllers.EpicorFunctionController.Post(Boolean production, String company, String library, String function, JObject data) in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Hosting\AspNet\RestApi\Epicor.RESTApi.EFxPlugin\Controllers\EpicorFunctionController.cs:line 69
   at lambda_method(Closure , Object , Object[] )
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.HttpServer.<SendAsync>d__24.MoveNext()

So I thought maybe it was sending JSON as a string? I changed my parameter to a string and tried to deserialize the object and got this:

System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type System.Data.DataSet. The token '"' was expected but found 'M'. ---> System.Xml.XmlException: The token '"' was expected but found 'M'.
   at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
   at System.Runtime.Serialization.Json.XmlJsonReader.ReadServerTypeAttribute(Boolean consumedObjectChar)
   at System.Runtime.Serialization.Json.XmlJsonReader.Read()
   at System.Xml.XmlBaseReader.IsStartElement()
   at System.Xml.XmlBaseReader.IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalIsStartObject(XmlReaderDelegator reader)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   --- End of inner exception stack trace ---
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader)
   at Epicor.Utilities.JsonSerializer.Deserialize[T](Byte[] bytes) in C:\_Releases\ICE\ICE4.1.100.7\Source\Shared\Framework\Epicor.ServiceModel\Utilities\JsonSerializer.cs:line 64
   at EFx.ESR.Implementation.DeleteMemoImpl.A001_CustomCodeAction()
   at EFx.ESR.Implementation.DeleteMemoImpl.RunStep(Int32 workflowStep)
   at Epicor.Functions.FunctionBase`3.Run() in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionBase.cs:line 90
   at Epicor.Functions.FunctionBase`3.Run(TInput input) in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionBase.cs:line 75
   at Epicor.Functions.FunctionRestAdapter`2.Run(IFunctionRestHost host, JObject input) in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionRestAdapter.cs:line 46
   at Epicor.RESTApi.Functions.Controllers.EpicorFunctionController.Post(Boolean production, String company, String library, String function, JObject data) in C:\_Releases\ICE\ICE4.1.100.0\Source\Server\Hosting\AspNet\RestApi\Epicor.RESTApi.EFxPlugin\Controllers\EpicorFunctionController.cs:line 69
   at lambda_method(Closure , Object , Object[] )
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.HttpServer.<SendAsync>d__24.MoveNext()

I don’t think that is possible right now using erp-function event action.
Suggest you use the rest-erp event action instead, and setup the dataview details on the Request Arguments.

AppStudio Help has an example of calling a EFx using the REST-ERP action.

1 Like

I’ll take a look at that.
Thanks!

1 Like

It seems the documentation has been updated to use the ERP-FUNCTION widget now. Any chance you can share a copy of the original or another example?

@Callum_Stott I just tried passing a dataset to an EFx using the REST-ERP.

Seems like it has a bug, the dataset did not actually get passed. I have asked someone to file a case for it.

The steps would be:

  1. Ensure that the EFx library is promoted to Production
  2. Launch AppStudio → Event Designer.
  3. Setup a new event with the desired trigger.
  4. Drag the REST-ERP widget
  5. Set it up with below:
    a. Call Options
    i. Library Name
    ii. API Key (this is optional from 2021.2 onwards)
    b. Service Operation should be the Function Name
    c. Setup the Method Parameters manually (if any)
    d. ERP Rest Arguments → Request Parameters – setup the View Name and Parameter Name (i.e. table name that the EFx expects)
1 Like

I thought Timothy Schilling had an example of this, have you reached out to him? I feel like we did something similar at insights, but not exactly this.

He said he would always respond because he always checks his email.

If you don’t have his email let me know!

I didn’t, no. I actually went a completely different direction.

Sorry, I should have come back to post an update. I did get it working in the end. Below is a JSONC code extract of the configuration I ended up using. It is working for me in 11.1.100.10 and was in 11.1.100.04 also. Thanks for your response and detailed steps!

“actions”: [
{
“type”: “rest-erp”,
“param”: {
“requestMethod”: “POST”,
“erpRequestMethod”: “ErpPostWithDataViewProcessing”,
“methodParameters”: [
{
“field”: “ds”,
“value”: null
}
],
“svc”: “OnChangePartNum”,
“svcPath”: “OnChangePartNum”,
“options”: {
“apiKey”: “Z5e4ftO6YdKfk8tAUKT47mevRE9x9tnjAeJ4mcqXraOfg”,
“efxLibrary”: “PbsReq”
},
“erpRestPostArgs”: {
“requestParamArgs”: [
{
“dataset”: {
“systemCode”: “ERP”,
“datasetId”: “PbsReq”,
“serverDataset”: “PbsReq”
}
}
],
“responsePath”: “outputDs”,
“processResponse”: true
}
}
}
],

2 Likes

Great stuff !

1 Like