Friday, December 29, 2017

Illegal entry in an array.

I have an issue that is returning a very strange error from Enterprise Portal.
Initially I receive the following in my browser:

An unhandled error has occurred. To view details about this error, enable debugging in the web.config file or view the Windows event logs.

Upon checking the event viewer on the EP IIS machine, I see the following:

An unhandled error has occurred. To view details about this error, enable debugging in the web.config file or view the Windows event logs.

Error executing code: Illegal entry in an array.

Stack trace

(C)\Data Dictionary\Tables\myTable\Methods\label - line 34


Microsoft.Dynamics.AX.ManagedInterop

   at Microsoft.Dynamics.AX.ManagedInterop.Record.CallWithReturnType(String methodName, Type returnType, Object[] paramList)
   at Microsoft.Dynamics.Framework.BusinessConnector.Session.DynamicsRecordAdapter.Call(String methodName, Object param1)

As of this writing, I have no idea what 'Illegal entry in an array' means.

Stay tuned...

UPDATE
Temporary Solution:
Well, I couldn't find a good solution for this. So here is the work around.
Original code throwing the error:

return mytable.myFieldArray[_arrayIndex];

Instead I do:

switch (_arrayIndex)
    {
        case 1:
            retValue = this.AttrFieldLabel[1];
            break;
        case 2:
            retValue = this.AttrFieldLabel[2];
            break;
        case 3:
            retValue = this.AttrFieldLabel[3];
            break;
        case 4:
            retValue = this.AttrFieldLabel[4];
            break;
    }

return retValue;

Hardcoding the index numbers on the array call seems to have solved my issue for now.

Happy coding!

Friday, December 15, 2017

SSRS Reports don't show labels

SSRS Reports aren't showing labels. Only Labels!@SYSxxxxx

This suddenly showed up after a code move.  It was preceded by an 'XppBridgeException' when running a single report (Print Invoice Journal).  There are a few posts out there with potential solutions such as checking your reporting service account password.  Our password never changes so there is no issue there.
I tried restarting the AOS.  Didn't work.  Cleared all cache.  Didn't work. Deployed all reports.  Didn't work.

Solution, hopefully, forthcoming...

Solution:

A Full CIL and reboot of our AOS servers and our SQL server has solved this problem.

Monday, November 6, 2017

Determine if code is running in Batch

Recently I was tasked with fixing an issue where our Project invoice proposals were not posting while in batch. 
I discovered that 'WinAPI' was being called in some custom code and was able to fix it.
However, I also realized that the custom code that was being used need to be called in Batch ONLY.  Due to some issues with Citrix and the AX Client, I had to prevent the AX Client from running this code.

This proved to be difficult as I was about 4 classes deep into Proposal posting and the isRunningBatch() method isn't available. (Or at least I couldn't find a way to get back to the 'RunBaseBatch' class).

So, I found a quick little solution that appears to be working:

xSession xSession = new xSession();
xSession.AOSName();

Whereas our batch server is never used for the client, I can just check the the AOSName against my batch server name and run code if they match.

Probably not the best solution, but it seems to work.

Thursday, October 5, 2017

A call to SPPI failed, see inner exception.

Out of nowhere we started receiving the following error on our EP/Sharepoint server.  It didn't seem to coincide with any events such as Windows Updates, code deployment, etc.

After searching, I found the the .axc files that EP and SSRS were using had been updated the day before this error showed up.  Not sure who or what updated them but it appeared they had their WCF Regenerated, only incorrectly.

I had the original .axc files so we simply replaced the bad ones with the known working versions, rebooted the EP and SSRS servers, and everything has worked great since!

I suspect we could have also done the 'Refresh' from the Config utility and that would have also worked.

A call to SSPI failed, see inner exception.
Microsoft.Dynamics.AX.Framework.Services.Client.UserSessionServiceException
at Microsoft.Dynamics.AX.Framework.Services.Client.ServiceClientHelper.InvokeChannelOperation[TResult,TChannel](IServiceClient`1 client, Func`2 operationInvoker, Func`2 exceptionWrapper)
at Microsoft.Dynamics.AX.Framework.Services.Client.UserSessionClient.GetAccessRights(IEnumerable`1 keys)
at Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts.ReportMenuItemHelper.HasAccess(MenuItemKey menuItemKey)
at Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts.AxReportViewerInternal.HasAccessToOutputMenuItemIfRequired()
at Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts.AxReportViewerInternal.CanPreRender()
at Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts.AxReportViewerInternal.OnPreRender(EventArgs e)
A call to SSPI failed, see inner exception.
System.ServiceModel.Security.SecurityNegotiationException
Server stack trace: 
at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream stream)
at System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper)
at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Thursday, September 21, 2017

SSRS Error 'Report schema already contains a dataset with name"'

While working on the PSAProjInvoice report, I suddenly received this error.  Literally... I generated one report, then generated another 5 minutes later and the error showed up.

So far, all the suggestions here haven't worked.

Looks like the only way I could get out of this mess was to export out older versions of the Report and DP and import them into my dev.  Make sure you export our your DEV versions so you have all the code changes and report design changes.  Then import the old versions and it should be good to go!

Tuesday, September 19, 2017

Workflow email approvals error 'The requested workflow action failed.'

We have external users who approve time sheets.  One of these users was attempting to approve time sheets when they received the error.  In looking at the event viewer on the server that was running the 'Mobile connector app' service, I found a 'Failed to log on to Microsoft Dynamics AX.'  Further investigation revealed that after a reboot 4 days ago, the service never fully started.
Once we restarted the service, everything worked!

Thursday, August 3, 2017

Trial balance dimension sets don't match

I had an issue with my customer where they would show one 'Closing amount' using Financial Dimension set A, and another 'Closing amount', using Financial dimension set B.


I was also getting strange behavior with reports as well.  If I ran the Trial balance in the form for Financial Dimension set A and then ran the Trial Balance Detail for the same set, it would differ in total amounts.

So, I ran a comparison of the two (if you click the 'Closing balance' it will show you the transactions that make up that amount).  I found the offending transactions fairly easily and then realized they weren't showing up in the 'Voucher transactions' form!

Further reasearch, mainly in table browsers, revealed that the GeneralJournalAccountEntry.LedgerDimension, for the above records, doesn't exist in DimensionAttributeValueCombination (RecId).  So, when that join is made, these records are left out.

How did this happen?  
UPDATE:
Looks like, potentially, a developer from our partner deleted the record in order to fix another problem.  A user was attempting to enter a segmented ledger account (Financial Dimensions), and it kept defaulting a particular segment.  So, I think they went into DimensionAttributeValueCombination and deleted the record in the hopes of preventing that field from defaulting. (I think it was just some cache).

Solution? 
UPDATE:
Well, I think the only solution, that is the quickest/simplest and lowest risk, is to recreate the record with the same RecId via SQL.  Then any of the other records that tied to this one via a LedgerDimension field on their respective table, should hook right back in.
UPDATE:
Going through SQL directly didn't work. It apears, however, that doing a new record and associating the new RECID of that record from DimensionAttributeValueCombination to other records in GeneralJournalAccountEntry, DimensionAttributeValueCombinationGroup, and DimensionAttributeValueCombinationStatus.

What's the moral of this story?

Don't delete records from DimensionAttributeValueCombination!!!

Wednesday, April 26, 2017

Electronic payment - NACHA file CCD addenda

My customer recently decided they wanted the ability to pay our vendors electronically.  Currently we use the Expense system and pay our employees via AP (Setting up employees as vendors).  We use EFT (Electronic funds transfer) to pay out those expenses.  However, we have been paying vendors via checks. We also needed to be able to pass along the Invoice numbers we were paying.

Our Employees get PPD NACHA files which are designed for personal accounts.  Our 'actual' vendors will get CCD NACHA files which are designed for company accounts.

To set this up, we need to go to Accounts payable -> Setup -> Payment -> Method of payment
Here are the settings I used which are based upon the employee 'EFT' we have setup for expenses.
Then, you need to setup the Payment specification.  This will then indicate that you want the CCD file and not the PPD. 'Payment specification' is located at the top of this form.
Here we have the correct 'Export format' selected.

We will start in the VendOutPaymRecord_NACHA_CCD class.  This is where all of our modifications will be made.  We will also look at the VendOutPaymRecord_NACHA class (the former's parent class) just for help to understand what we are doing.

First we will want to overrid the 'fillField10()' method in the 'CCD' class.
All the code will be the same except:

#define.addendaIndicator('1')

We changed the '0' that is in the parent class to '1' in the 'CCD' class.  This tells us that the 'Detail' record on our 'CCD' file will contain 1 'Addenda' record. We want our PPD file to remain as it always has with 0 addenda records.

Next we want to go to the 'output()' method on our 'CCD' class and this is where we will 'Fill' our addenda line.  After the 'file.writeExp(nacha_ccd_Recrod);' we can do:

file.writeExp(this.FillInvoiceAddenda())

Create the 'FillInvoiceAddenda()' method:
protected container FillInvoiceAddenda()
{
    container addenda;
    #define.seven('7')
    #define.inv('INV ')

    str 80 invoiceAddenda = #seven + #inv + this.parmCustVendPaym().recieversInvoiceNumber();
    addenda = conIns(addenda, 1, invoiceAddenda);

    return addenda;
}

the 'parmCustVendPaym()' comes from parent classes (If you trace it back it is the CustVendOutPaymRecord class) and it contains pretty much all the information about the 'sender' and the 'reciever'.  Great place to look for additional information.

This is simply a container with 1 record in it.  We define the '7' because that is required for the NACHA file.  The 'INV' is simply extra and is supposed to indicate 'Invoices' to the vendor.  Remember, you only have 80 Characters.  In my case, we were going to show the Invoices on this addenda line.  That could get long depending on how many invoices and how long the invoices are.

Here is a sample of the NACHA CCD file detail and addenda line

43615200325442821342         0000215280V-001001       My Vendor          1GJ-041478000001
705INV123TEST, 123aTEST

***NOTE:  I haven't had a chance to test the addenda lines, however, I'm fairly certain that it will work.
***Update:  Looks like I may need to have '705' for the beginning of my addenda line.

The entire file has more than that, however, there was no need at this point to modify anything else.

That's it.  Incremental CIL and you can test this by 'Generating payments' in a Vendor 'Payment journal'.



Friday, March 17, 2017

Unable to find Vendor Invoice

Unable to find Vendor Invoice

Yesterday, an AX user was attempting to create a Vendor Invoice from a Purchase order.  In the middle of that operation, his client lost connection to the AOS due to a network issue.

After that, we couldn't find the invoice anywhere.  It didn't get posted and it wasn't in 'Pending' or 'Open' Vendor invoices.  After doing a little research, I found this post which had a couple different solutions to try.

Deleting the record in 'Accounts receivable -> Inquiries -> History -> Invoice history and matching details' worked perfectly.

Thanks to 'ERP Software Blog', whoever you are, for the post!