Friday, November 8, 2019

WCF Web Service Receiving Null Parameter

I was recently working with a client application (WPF) that used WCF Web Services to query and post data to Dynamics Ax (2012). One the requirements needed a new web service to be deployed.  I once again reached one of those situations where the service worked in development and it passed testing with no issues.  However, in 2 of roughly 10 sites, it started failing. One of my associates started debugging and found that the client application was sending the data, however the web service was receiving a null parameter.  I should mention that the parameter was being sent as content data in a post request in json format.

Getting copy of the data being sent was not much of problem.  I then emulated the call using Postman.  Irritatingly, it worked. So, it works in Postman and does not work in the client application and we were almost stumped.  As a last ditch attempt, I rewrote the sending routine to iterate through the records and send 5 records to be processed only.  The routine failed on the second iteration.  Debugging the call and extracting the data, I found that there was a French character in the stream.  Rechecking the settings on Postman, I found that the Postman was using UTF-8.  Honestly, I thought this would be default these days, but I guess I was mistaken.  I modified the call to force it to use UTF-8 and it worked.

For reference:
using (WebClient client = new WebClient())
{
     client.Headers[HttpRequestHeader.ContentType] = "application/json";
     client.Encoding = Encoding.UTF8;

     …<do other stuff>
     var dataString = client.UploadString(apiUrl, jsonObj);
     ResponseClass webresult = JsonConvert.DeserializeObject<ResponseClass>(dataString);
}

Tuesday, June 25, 2019

WPF: Validation and Dependency Objects

I recently had to do some support work for a WPF application.  I had not used WPF or MVVM in several years, so it was a nice change.  However, one of the requirements was to create a range validator and attach it to textbox.  The architecture of this part tied the View to the base class of a View Model that had several derived classes.  Each derived class had different minimum and maximum boundaries that needed to be reflected when the view was opened.

There were a couple of very good treatments that I found.  The process is as follows:
  1.  Create the Min and Max Properties in the View Model.
  2.  Create a class derived from ValdationRule.
  3.  Create a wrapper class derived from DependencyObject.  The Dependency Properties will represent the min and max that you need.
  4.  Add a property of the wrapper class in the Validation Rule.
  5.  Create a class derived from Freezable that will enable the View to access the DataContext and pass values to the wrapper.
  6.  Add the elements to the View.  If done properly, the Min and Max needed by the wrapper can be set to values defined in the ViewModel.

Tuesday, March 19, 2019

Ledger Dimension

I finally learned...A basic dimension is a default dimension.  This is a value that concatenates a number of dimension values and is located in the Dimension Attribute Value Combination Table.  If you add a Main Account, then you have a Ledger Dimension.  The combination that you may try to retrieve or create MUST be part of the Main Account's Account Structure.

There are 2 approaches to getting a Ledger Dimension
1) Query it with AxdDimensionUtil::getLedgerAccountId
2) Create or retrieve it with DimensionDefaultingService::serviceCreateLedgerDimension

The code to retrieve a Ledger Dimension is:

private DimensionDefault getLedgerDimension(MainAccountNum _mainAccount, Num, str _bu, str _costcenter, str _dept)
{
    DimensionDefault result = 0;
    int position = 0;
    int dimensionCount = 0;
    container account;

    account += [_mainAccountNum, _mainAccountNum, 0];
    if(_bu)
    {
        account += ['BusinessUnit', _bu];
        dimensionCount++;
    }
    if(_dept)
    {
        account += ['Department', _dept];
        dimensionCount++;
    }
    if(_costcenter)
    {
        account += ['CostCenter', _costcenter];
        dimensionCount++;
    }

    account = conPoke(account, 3, dimensionCount);
    try
    {
        result = AxdDimensionUtil::getLedgerAccountId(account);
    }
    catch
    {
        return 0;
    }

    return result;
}


The code to called serviceCreateLedgerDimension requires a Main Account Number and Default Dimension:

private DimensionDefault getLedgerDimensionFromDefaultDimension(MainAccountNum _mainAccountNum, DimensionDefault _defaultDimension)
{
    DimensionDefault result = 0;
    DimensionDefault ledgerDimension;

    container account = [_mainAccountNum,_mainAccountNum, 0];
    ledgerDimension = AxdDimensionUtil::getLedgerAccountId(account);
    result = DimensionDefaultingService::serviceCreateLedgerDimension(ledgerDimension, _defaultDimension);

    return result;
}

Tuesday, March 12, 2019

D365 FO and External DLLs

We recently had to add some external dlls to our D365 for Finance and Operations model.  We found out that when the references are added to a project, an XML descriptor of the reference is placed in $\LCS Dynamics Ax\Trunk\<your branch>\Metadata\<your model>\<your model>\AxReference.  However, once you ready to deploy, the actual dll must be manually added to $\LCS Dynamics Ax\Trunk\<your branch>\Metadata\Bin.  Otherwise, the LCS build will fail with a class not found error.

Friday, February 8, 2019

Positive Pay in D365 For Finance and Operations for 8.1

One of my clients recently upgrade to D365 version 8.1.  This was a Microsoft mandated change as this is the one where overlays will no longer be allowed.  After the dust settled, I was asked to make some changes to their Positive Pay files.  The process worked in their previous environment, however under 8.1 the documents were being produced without data.

After debugging the process, I was able to isolate the issue to the MS side of code.  Specifically, the DMF process was not able to find the required records.  I raised a ticket with MS and they resolved it in short order.  There appears to be a breaking change in 8.1 there the entity name must be capitalized in the XSLT file.

So instead of the old:

Document/BankPositivePayExportEntity

You need to put:
Document/BANKPOSITIVEPAYEXPORTENTITY

The documentation from MS has not been updated  yet.