Tuesday, November 25, 2014

Monday, November 17, 2014

Thoughts on validateField

Here is a couple of thoughts on how to write validateField methods in the best possible way.  The validateField method is automatically called when you change a field value of a record in the client.

There are two things about validateField, that I haven't been able to figure out:

  • Is the method originally intended to be called only when a field value is changed, or should you also be able to call it to validate the current value?
  • Why do AX 2012 also have a name based validateFieldValue method?

I raise the first question because the standard AX data consistency check actually calls validateField on existing data to check the present value of the fields. That gives a number of errors from standard AX, that really isn't errors but appears so because the code on the field assumes you have modified the field value from something else to the present value.

One example of this, is the many errors you get from Currency:

In this case you could add code to see if the value actually is changed.

Also some validations should check that the field actually has value. One example from standard AX of a validation not doing this is license plate validation on warehouse locations, where a blank value in some fields will give you this error:

Here the validation looks up another location using a blank value, and the returned flag for License Plate Control will of course be blank.

Don’t update data in a validation method. You should always be able to call a validation method without risking any data to change in the system. Changes should be moved to the modifiedField, modifiedFieldValue, update or insert method.

Don't display any dialogs from the table based validation method without checking if the validation method is being triggered from a form data source. The code analysis tool on LCS will report this as a Best Practice issue, as the validation could be called from a server tier. Consider moving these dialogs to the forms where needed.

Friday, November 14, 2014

Search available icons from embedded resources

I was today made aware of this clever searchable cross reference like tool for finding places where image resources are used in AX:

You can read more about the tool and download it here: http://axaptanotes.blogspot.com

Thursday, November 13, 2014

Required check and update when deleting a backing entity for a financial dimension

When you delete a record that is also a backing entity for a financial dimension, you need to check that the financial dimension framework allows you to delete the backing entity and you need to update the financial dimension as being deleted.

This is done in the delete method of the backing entity.
The check takes place outside TTS:
// Check to see if the associated dimension attribute value has been used
// in a way that would prevent deletion.
if (!DimensionValidation::canDeleteEntityValue(this))
    throw error(strFmt("@SYS134392", this.PersonnelNumber));
And the update takes place within TTS:
// Update the associated dimension attribute value.

Examples of this can be found several places in standard AX, for example on the tables:
  • ProjTable
  • HcmWorker

Monday, October 20, 2014

Quick tip: New classes for sending mail in AX 2012 R3

In AX 2012 R3 there is a new framework for sending e-mail. Entirely based on .NET API's. A lot of standard code sending mail has taken up this new framework.

It seems that you'd require .NET 4.5 in order to use it.

Check SysMailerNet on MSDN.

Tuesday, September 30, 2014

The nuts and bolts of Lync / Presence / IM integration

I recently had to figure out what makes the "Presence" integration tick. I didn't find any really good explanations to work from, so here I'll try sum up the bits that makes this work. I'll try to boil the information down to the bare minimum of what you need to know. The feature is actually very flexible and I don't want this to be a very long post with information about tons of ways to use it.

Okay, first of all you'll need to have a Lync client installed along with your AX client. And you need to be logged into Lync with your account for that.

Next you'll need to add some contacts in AX. You must create an address of type e-mail and fill the address with the e-mail address this contact uses for instant messaging (IM). Please observe that some people have different e-mail addresses for regular e-mail and for IM.

In the contact form you must click the More options / Advanced button and check the "Instant messenger sign-in" check box. This tells AX to use this particular address of the contact when integrating with Lync. If the address is only used for IM and not also for regular e-mail, check the "Instant message" check box too.

When you want to show the presence indicator next to a field on a form, there are three properties of the form field to consider:
  • PresenceIndicatorAllowed. I assume you can guess what this controls.
  • PresenceDataSource and PresenceDataField. This is the datasource and datasource field from the form that holds data used to find the right contact with.
The last thing, is to control how the contact person is found and set up a PresenceInfo object. 

There are different approaches for different kinds of key data. Here AX looks at the extended data source of the PresenceDataField that you specified on the form field. 

On the extended data type there are two properties pointing to the class method doing the job of finding the contact person. The properties are PresenceClass and PresenceMethod. I think all standard implementations of these point to the DirPresenceInfo class as the PresenceClass. If you examine this class you can see how it based on different kinds of keys finds the right contact person and creates a PresenceInfo object for the contact.

That's all.

Tuesday, September 16, 2014

Send tweets from AX via the Retail module

Once again I fell over some objects with interesting names in the retail code. This time I learned that you can update Twitter and Facebook from AX.

In the following I'll describe the Twitter setup.

First of all, you need to setup an application under your Twitter account. Go to https://apps.twitter.com/ to do that. Under settings, you need to fill in:
  • Name: This will be the name of your application. Mine is called PalleAgermarkTest.
  • Description: This shows when for example you later on link the application to be able to use your Twitter account.
  • Website: This should a website where users can download the application. Since I don't have a real application, I have just put the address of my blog.
  • Callback URL: This is needed when AX links the application to your Twitter account. Again, the address is not important (but an address is needed) for this demonstration and I have again put the address of my blog here.
On the API tab of the setup, you'll get an API key and an API secret. You will need these in AX.

On the Permissions tab, give the application write access to the Twitter accounts that sign up to the application:

That's it for Twitter.

Go to Retail \ Setup \ Parameters \ Retail parameters to setup some seed data for the retail module. Click the Initialize button:

Now in AX, go to Retail \ Setup \ Parameters \ Retail shared parameters and enter the API key secrets from above:

Then go to Sales and marketing \ Setup \ Campaigns \ Media types and add Twitter as a media type:

Now when clicking the Link account button, you should get the option to link your Twitter account (the screen clip is in Danish, but you should be able to get the idea):

So now all the bits and pieces are setup, and a very simplified piece of code like this example is able to post to Twitter:

static void Tweet(Args _args)
    smmCampaignMediaTypeGroup           mediaTypeGroup;
    RetailMediaChannelConnectorSettings settings;
    RetailMediaChannelTwitterConnector  connector;
    RetailMediaChannelMessage           message;

    select firstOnly TableId from mediaTypeGroup
        where mediaTypeGroup.CampaignMediaTypeDescription == 'Twitter'
    join settings
        where settings.smmCampaignMediaTypeGroup == mediaTypeGroup.CampaignMediaTypeId;

    connector = RetailMediaChannelTwitterConnector::construct(settings);
    message = RetailMediaChannelMessage::construct();
    message.parmMessage("Tweet from AX");

The result: