martes, 11 de febrero de 2014

Exam MB6-869 :: Microsoft Dynamics AX 2012 Development Introduction

Got it!  Yeah!
“Microsoft is a registered trademark of Microsoft Corporation in the United States and other countries."

Below are a few exam tips, from my personal experience.


* Unfortunately no Packt Publishing MB6-869 exam cookbook exists so we have to go to MSDN for our study material.  The links below are no way complete (or we have links with too much information related to the published exam content), but these may help you quickly locate topics covered within the exam for AX 2012.

* Your important first steps would be to take a look at the two Microsoft Development I & II e-learning courses if you have access to them, while a few errors exist in them they are excellent at summarising the MSDN documentation.

* If, like me, you work in a non-English company I suspect that the exam will be a tiny bit more difficult as it’s only available in English, Japanese and Chinese.  Why not change your MorphX settings to English and familiarise yourself with those terms used in the exam?  It took me a while to get used to the changes from the Spanish setting, and I’m a native English guy!

* Pay particular attention to the relative percentages of the exam.  Putting a bit of effort in the Exception handling section is a steal compared to some of the other exam topics that we need to trawl through.  However, even this apparently simple section will have it’s nuances to be aware of

* Go play.  For example, the sections related to Valid time state tables, Security, Eventing and Form parts you may never have encountered these in your day-to-day job so you could then either make an excuse to work with them, or go home and construct them on a virtual machine.

* No one will ever accuse you of ‘slacking off’ at work if they find you reading MSDN!  I have found that 15 minutes preparing for the exam during my 11 hour a day working week can provide a great foundation for not only exam study but also for gaining useful knowledge that can be later applied to your daily work tasks/responsibilities.  In fact this whole exercise has given me more confidence when making technical recommendations to other staff.

* If the company that you work for is associated with the Microsoft Partner Network, you can associate their name after passing the exam.  If it’s a serious organisation you should ask your supervisor if they can pay the exam fees for you and give you the time off to actually take the exam, as they will benefit from your certification as well.

* Last minute exam cramming?  Try diving into the fantastic "Microsoft Dynamics AX Topology and architecture diagrams". Or consume like a velociraptor these slide-shows 1, 2, 3.

* Feel free to add any suggestions and corrections to the comments below, as it’s obvious that I haven’t got a 100% handle on some sections…  Good luck!


Microsoft Dynamics AX 2012 Development Introduction (correct as of August 29, 2011)

Microsoft E-Learning (PartnerSource):
* 80304AE: Development II in Microsoft Dynamics AX 2012 (4 Hours)
* 80303AE: Development I in Microsoft Dynamics AX 2012 (3 Hours)

Exam Topics Covered -  The following list includes the topic areas covered on this exam:
* Understanding Dynamics AX 2012 Architecture
* Managing the Data Dictionary
* Managing the User Interface
* Managing Security
* Working with X++ Control Statements
* Managing Objects and Classes
* Accessing the Database
* Managing Exception Handling


+Understanding Dynamics AX 2012 Architecture (13 percent)
- Identify key development features and functionality.
  This topic may include: development workspace; IntelliMorph(1); MorphX(1,2); object-oriented design(1); navigation(1?)
- Demonstrate understanding of the data architecture.
  This topic may include: working with data in forms; sorting records; filtering records(2); finding records
- Demonstrate understanding of architecture components.
  This topic may include: layers; models(1); labels(1); Help system (1,2); reporting (1)
- Work with customization tools.
  This topic may include: using MorphX to customize the user interface; using the X++ editor to develop customizations; identifying best practices(1); using the Type Hierarchy Browser and Type Hierarchy Context tools; using the reverse engineering tool
+Managing the Data Dictionary (13 percent)
- Work with MorphX, the Application Object Tree (AOT), and projects.
  This topic may include: working with development projects; features of the AOT (1); Microsoft Visual Studio projects node(1,2,3); objects in the data dictionary; navigating the AOT and data dictionary
- Work with tables and relations.
  This topic may include: table structure and components(1,2); fields; field groups (1); indexes (1); delete actions(1,2,3); creating tables; creating relations(2, 3, 1, 4, 5); (1) primary keys; foreign keys; surrogate keys
- Work with data types and base enumerations.
  This topic may include: primitive types; extended types(1,2); creating data types(3); using data types(1); creating base enumerations(1,2,3); using base enumerations
- Work with maps and views(1).
  This topic may include: map functionality(1); map advantages; view functionality(1); view advantages
+Managing the User Interface (13 percent)
- Work with menus and menu items.
  This topic may include: creating and using menu items(1,2,3,4); menu functionality(1,2); creating menus
- Manage forms.
  This topic may include: data sources(1); design(1,2,3); document view(3?,1&2?); editing data in a form
- Work with forms.
  This topic may include: form types(2,1); list pages(1) and list page metadata(1); working with the action pane; form parts(1)
+Managing Security (11 percent)
  This topic may include(1,2): identifying key concepts, terms, and benefits(1); working with roles(1), process cycles(1), and duties(1,2); working with privileges(1,2), entry points(1), and permissions(1,2,3)
- Understand security concepts and settings.
  This topic may include: default security settings(1?,2? (search: ‘default’ - see standard roles : -SYSADMIN-, SystemUser, HCMEmployee),3?); sample security settings
- Work with XDS and server enforcement of security.
  This topic may include: server-based code authentication(1,3,2); data security filters; org model(1,2(see section ‘Extensible data security’)); effective date(1,2(select ‘Date Effective Patterns’ to download))
+Working with X++ Control Statements (13 percent)
- Work with variables.
- Work with operators.
- Work with conditional statements(1) and loops(1).
- Work with communication tools.
This topic may include: print; boxes(1); infolog(1!,2,(3),4,5); dialog(3,4,2,1)
+Managing Objects and Classes (12 percent)
- Work with classes(2,1,3), objects, and inheritance.
  This topic may include: defining key attributes(2,1,3!); method access control((1,2,3,4?)); extending a class(1); expression operators for inheritance(1); referencing object methods(2,1); method types(1); inheritance among tables(1,2,3)
- Work with scoping, events, and parameters in X++.
  This topic may include: scope of objects within a class(1,2); events in X++(1)
+Accessing the Database (15 percent)
  This topic may include: table buffers; select statements(1,2); field lists(1,(2)); while select statements; sorting; joins(1,2); cross-company data access(1)
- Manipulate data.
- Work with queries(1).
  This topic may include: executing a query(1); building a query(1,2); QueryBuildDataSource(1); QueryBuildRange(1)
+Managing Exception Handling(1,2) (10 percent)
- Work with exceptions and optimistic concurrency(1) exceptions.
  This topic may include: handling errors(1,2,3,4,5)
- Work with throw and try/catch commands.
  This topic may include: handling errors

miércoles, 29 de enero de 2014

Cube measurement data, or lack there-of

Sometimes when migrating hand-crafted cubes from the development environment to production you get that sinking feeling when no transactions totals appear in the SQL Management Cube Browser.  The culprit in my experience is one of four reasons:
  • No data!  This is not actually a problem, except for live-testing. Sometimes rollouts start by using the sales and ledger module so no one has yet started inputting purchase orders into the production system. Be aware of the issue.
  • RecId differences, usually on the financial dimension sets.
    I really must write another blog post on this, but using AX to publish your cubes is preferred.
  • Virtual company/Table collection issues. As a developer be aware if virtual companies exist and how they are configured with regards to companies and table collections.
    GLOB : US : CON (Contoso DataAreaId)
    Things get worse if there are differences between your development environment and production.  Manually attempting to perform a join on this example in MSDN is going to be difficult so use AOS generated views to do this for you.
  • Eumeration label issues/SRSAnalysisEnums.  THIS issue stung me today, and has done so in the past.  Basically the cubes rely on a per installation generated table called SRSAnalysisEnums to populate the dimension attributes.  There is a great post detailing this for us, the job below will populate this table.  Remember, it may not be populated in some environments.  ALSO remember that if the enumeration does not exist in an AOS perspective, it won't get generated.  Add the table to a new perspective if you have not already do so, and relaunch the generation process. It will take a few minutes.
///If the enum doesn't exist in a Perspective, it won't get added...
///Only 'en-us' values?  See table 'BIUdmTranslations' and check those that require BI labels generated for them.
static void ZZZ_PopulateSRSAnalysisEnums(Args _args)
{;
    BIGenerator::populateSRSAnalysisEnums();
}

If like me you are in a hurry for ONE enumeration that's missing, try this job that inserts or updates the BankAccountHoldStatus value with the enumeration name that you require.
///Only 'en-us' values?  See table 'BIUdmTranslations' and check those that require BI labels generated for them.
static void ZZZ_PopulateSRSAnalysisEnums(Args _args)
{
    //;
    //BIGenerator::populateSRSAnalysisEnums();
    
    // ...Or, populate one concrete enum labels entity
    // ----------------------------------------------------------
    str enumName = 'BankAccountHoldStatus';
    // ----------------------------------------------------------
    
    // Macros and defines
    #AOT
    #Properties
    #SRSModel
    #BIFramework

    SRSAnalysisEnums analysisEnums;

    Set dictEnumSet = new Set(Types::Class);
    Set languageIdSet = new Set(Types::String);

    SetEnumerator dictEnumEnumerator;
    SetEnumerator languageIdEnumerator;

    TreeNode enumNodeRoot = TreeNode::findNode(#BaseEnumsPath);
    TreeNode enumNode;
    TreeNode enumItemNode;

    DictEnum dictEnum;

    int valueIndex;
    str labelId;
    str label;

    SRSEnumName enumItemName;
    SRSEnumValue enumItemValue;

    LanguageId languageId;

    void populateLanguageIdSet()
    {
        BIUdmTranslations translations;
        ;

        BIUdmTranslations::initialize();

        while select LanguageId, Generate from translations where translations.Generate == 1
        {
            languageIdSet.add(translations.LanguageId);
        }

        // add the default language if nothing is currently selected
        if (languageIdSet.elements() == 0)
        {
            languageIdSet.add(@"en-us");
        }
    }

    void addEnumToDictEnumSet(str _enumName)
    {
        DictEnum enum = new DictEnum(enumName2Id(_enumName));
        
        if (enum && !dictEnumSet.in(enum))
        {
            dictEnumSet.add(enum);
        }
    }

    str getLabel(LanguageId langId, str lId, str defaultName)
    {
        str value = #emptyString;
        ;

        if (lId)
        {
            value = SysLabel::labelId2String2(lId, langId);
        }

        if (value == #emptyString)
            value = defaultName;

        if (strLen(value) > #smMaxLengthEnumItemLabel)
        {
            value = subStr(value, 1, #smMaxLengthEnumItemLabel);
        }

        return value;
    }
    
    ;

    populateLanguageIdSet();
        
    addEnumToDictEnumSet(enumName);
    
    // Populate the SRSAnalysisEnums table
    dictEnumEnumerator = dictEnumSet.getEnumerator();

    ttsbegin;

    while (dictEnumEnumerator.moveNext())
    {
        dictEnum = dictEnumEnumerator.current();

        if (dictEnum == null)
        {
            continue;
        }

        enumNode = enumNodeRoot.AOTfindChild(dictEnum.name());

        for (valueIndex = 0 ; valueIndex < dictEnum.values(); valueIndex++)
        {
            labelId = #emptyString;

            enumItemName = dictEnum.index2Symbol(valueIndex);
            enumItemValue = dictEnum.index2Value(valueIndex);

            if (enumNode)
            {
                enumItemNode = enumNode.AOTfindChild(enumItemName);

                if (enumItemNode)
                {
                    labelId = enumItemNode.AOTgetProperty(#PropertyLabel);
                }
            }

            languageIdEnumerator = languageIdSet.getEnumerator();

            while (languageIdEnumerator.moveNext())
            {
                languageId = languageIdEnumerator.current();

                label = getLabel(languageId, labelId, enumItemName);

                select firstfast forupdate EnumName, LanguageId, EnumItemName, EnumItemValue, EnumItemLabel
                    from analysisEnums where analysisEnums.LanguageId == languageId && analysisEnums.EnumName == dictEnum.name() && analysisEnums.EnumItemValue == enumItemValue;

                if (analysisEnums)
                {
                    if (analysisEnums.EnumItemName != enumItemName || analysisEnums.EnumItemLabel != label)
                    {
                        analysisEnums.EnumItemName  = enumItemName;
                        analysisEnums.EnumItemLabel = label;
                        analysisEnums.update();
                    }
                }
                else
                {
                    analysisEnums.EnumName      = dictEnum.name();
                    analysisEnums.LanguageId    = languageId;
                    analysisEnums.EnumItemName  = enumItemName;
                    analysisEnums.EnumItemValue = enumItemValue;
                    analysisEnums.EnumItemLabel = label;

                    analysisEnums.insert();
                }
            }
        }
    }

    ttscommit;
}


lunes, 9 de diciembre de 2013

Cannot create a record in Reporting Services entity cache (SRSModelEntityCache). Entity identifier: XXX, An AX view entity. The record already exists.

Creating a new analysis services project I encountered the following error:
Cannot create a record in Reporting Services entity cache (SRSModelEntityCache). Entity identifier: 7542, An AX view entity. The record already exists.
The message is almost trying to be helpful, providing us the id of the object that is duplicated.
Stepping through my various views associated to the perspectives, I realised that I had done a very silly thing(TM).  I would effectively be adding the same entity to the various cubes twice.  In this case to the shared dimensions perspective.

Perspectives under the microscope

Remember that the wizard for generating cubes adds certain views for us.  The following selection would add the offending BIExchangeRateView.  As you can see from the above image, perhaps I should remove other BI* views as well, although BISampleOrgHierarchyView may be okay.



viernes, 15 de noviembre de 2013

Function SRSTmpTblMarshaller::SendTmpTblToDataProvider has been incorrectly called.

Error:
Function SRSTmpTblMarshaller::SendTmpTblToDataProvider has been incorrectly called.
Solution:
Change the table buffer TableType property used to 'feed' your SSRS report to InMemory.  This is a pain for me as I am working with Tax transactions and wanted the TempDB type, which would avoid storing thousands of rows in the AX client memory.

martes, 1 de octubre de 2013

An export format or a method of payment with an export format must be specified.

An export format or a method of payment with an export format must be specified.

To resolve the error I had to move the current execution point from the CustVendSumForPaym class, constructor method,  "custVendSumForPaym.getLast();" line to avoid looking in the cache (SysLastValue) and retrieving a payment method format that does not exist.  I was asked to rename a file format method text that I had created, and had referenced this class during my testing.  I tried both clearing the cache and restarting the AOS but was unsuccessful attempting to remove the reference to the previously selected payment settings.

The source of my woes.
Edit: Not tried physically deleting the UAC (Ax User cache) file.

miércoles, 14 de agosto de 2013

SQL DB backup and restore data


We're performing a database backup and restore across a different AOS instance today (AX 2012 R2).  Great fun.  Fortunately in my case we are doing it within the same domain which helps considerably.

The first thing to do is perform the SQL Backup of the server, so that we can then apply a restore on a different AOS installation. Before that though, see the fantastic MSDN blog post 'Moving between Microsoft Dynamics AX 2012 Environments' and it's asociated Word document.  Note the comment about checking that the two installations must be of the same 'state' to be able to do this.  It's essential to have both services with the same patches and models applied.

Below is my thrown together list of SQL commands I've generated while going through the document attached to the blog, adding a few of my own entities such as the DMF framework parameters.  Run the select commands below and write the output to a file, before performing the restore to ensure that you have the original values saved somewhere.  The Make sure to change the <01@NewAOS> and <02@OldAOS> placeholders with the actual AOS instance name.  Also the server names for <SRV01> (and <SRVDB> for the reports/cubes/db) and <SRV02> placeholders will require changing.  I've not needed to create scripts for saving users across domains, as I said before.

-- ESSENTIAL: Verify the Kernel and Application versions in the Database 
print '>> Kernel and Application versions'
select * from SYSSETUPLOG where DESCRIPTION = 'finished' order by CREATEDDATETIME desc

-- AIF, check for more than one Web site!
print '>> AIF'
select * from AIFWEBSITES
/*
update AIFWEBSITES set URL = 'http://SRV01/MicrosoftDynamicsAXAif60' where URL = 'http://SRV02/MicrosoftDynamicsAXAif60'
update AIFWEBSITES set NAME = 'SRV01-Default Web Site-MicrosoftDynamicsAXAif60' where NAME = 'SRV02-Default Web Site-MicrosoftDynamicsAXAif60'
update AIFWEBSITES set VIRTUALDIRECTORYSHARE = '\\SRV01\MicrosoftDynamicsAXAif60' where VIRTUALDIRECTORYSHARE = '\\SRV02\MicrosoftDynamicsAXAif60'
*/

-- Batch and AOS
print '>> Batch and AOS'
select * from SysServerConfig
select * from BatchServerConfig
select * from SysClusterConfig

select * from BatchServerGroup
select * from Batch

/*
update BatchServerConfig set SERVERID = '01@NewAOS' where SERVERID = '01@OldAOS'
-- SysServerConfig will get updated if you have already started the AOS, but it will not be treated as a batch server.
update SysServerConfig set enablebatch = 1 where SERVERID = '01@NewAOS'
--update SysServerConfig set CLUSTERREFRECID = '5637144576' where SERVERID = '01@NewAOS'
--update SysServerConfig set SERVERGUID = '724181F9-3740-4A6D-8850-3749F514011F' where SERVERID = '01@NewAOS'

update Batch set SERVERID = '01@NewAOS' where SERVERID = '01@OldAOS'
update BatchServerGroup set SERVERID = '01@NewAOS' where SERVERID = '01@OldAOS'
*/
-- BI and SRSS
print '>> BI and SRSS'
select * from BIANALYSISSERVER
select * from BICONFIGURATION
select * from SRSSERVERS

/*
-- Execute the below for *each* cube deployed, e.g. 'PurchCube'
update BIANALYSISSERVER set SERVERNAME = 'SRVDB' 
 --, DEFAULTDATABASENAME = 'PurchCube initial'
 where SERVERNAME = 'SRV02'
 -- and DEFAULTDATABASENAME = 'PurchCube'

-- Do *each* of your modified db cube databases have the same name?...  Project file location?...
update BICONFIGURATION 
    set CONNECTIONSTRING = 'Provider=SQLNCLI10.1;Data Source=SRVDB;Integrated Security=SSPI;Initial Catalog=MicrosoftDynamicsAX'
        --,PROJECTFILENAME = 'C:\Users\usr1\AppData\Local\Temp\2\PurchCube2\PurchCube.dwproj'
        --,PROJECTNAME = 'ZZZCubes'
    where CONNECTIONSTRING = 'Provider=SQLNCLI10.1;Data Source=SRV02;Integrated Security=SSPI;Initial Catalog=MicrosoftDynamicsAX'
        -- and PROJECTFILENAME = 'C:\Users\usr1\AppData\Local\Temp\1\PurchCube\PurchCube.dwproj'
        -- and PROJECTNAME = 'Dynamics AX'

-- Reporting
update SRSSERVERS set SERVERID = '01@NewAOS',
     SERVERURL = 'http://SRVDB/ReportServer',
 REPORTMANAGERURL = 'http://SRVDB/Reports',
 AOSID = '01@NewAOS',
 CONFIGURATIONID = 'SRVDBMSSQLSERVER',
 AXAPTAREPORTFOLDER = 'DynamicsAX',
 SERVERINSTANCE = 'MSSQLSERVER'
    where serverid = '01@OldAOS'

--It is recommended to redeploy new ODC files (users should ensure all connections strings have correct server names and databases.)
--Redeploy any Enterprise Portal changes that exist in the AOT to the test EP website.
*/

-- Document Management
print '>> Document Management'
select * from SystemParameters
/*

*/

-- Help Server, Performance thingy
Print '>> Help Server, Performance thingy'
select VALUE from SYSGLOBALCONFIGURATION where NAME = 'HelpServerLocation'
select VALUE from SYSGLOBALCONFIGURATION where NAME = 'SCOMPERFORMANCEAOS'
select * from SYSGLOBALCONFIGURATION 
/*
update SYSGLOBALCONFIGURATION set VALUE = 'http://SRV01:8080/DynamicsAX6HelpServer/HelpService.svc' 
    where NAME = 'HelpServerLocation' AND VALUE = 'http://SRV02/DynamicsAX6HelpServer/HelpService.svc'
update SYSGLOBALCONFIGURATION set VALUE = '01@NewAOS' 
    where NAME = 'SCOMPERFORMANCEAOS' AND VALUE = '01@OldAOS'
-- Customisations on the AOS?  Check if the max table join limit has been changed but there's no need to update the value
--update SYSGLOBALCONFIGURATION set VALUE = '30'
--    where NAME = 'MAXJOINLIMIT' AND VALUE = '26'
*/

--System Service Accounts, AX user accounts
print '>> System Service Accounts, AX user accounts'
select * from SysBCProxyUserAccount
select * from SysWorkflowParameters
select * from userinfo
Select * from sysServerSessions

/*
-- Launch the command line, as we need to update the userinfo where id = 'admin'
cmd.exe C:\Users\jondoe>Whoami /user
INFORMACIÓN DE USUARIO
----------------------
Nombre de usuario SID
================= ==============================================
DOMAIN\jondoe     S-1-5-21-1362911470-1944611129-2500288337-1131

-- To obtain other domain user SIDs see http://technet.microsoft.com/en-us/sysinternals/bb897417.aspx (Translates SIDs to names and vice versa)
*/

/*
-- Business Connector
update SysBCProxyUserAccount set SID='S-1-5-21-1362911470-1944611129-2500288337-1132', Networkdomain = 'DOMAIN.INT', networkalias = 'AXPROCON' 
    where SID = 'S-1-5-21-1362911470-1944611129-2500288337-1123'

-- Workflow is activated?
-- update SysWorkflowParameters set EXECUTIONUSERID = 'Admin' 
--    where EXECUTIONUSERID = 'wfexc'

--With a change of domain, update the key users and I suggest to delete all of the other users and reimport.
--Changing the Microsoft Dynamics AX *admin* users account to new Domain Account information 
select SID, Networkdomain, networkalias from userinfo -- where networkalias = '<user_alias>'
update userinfo set SID='S-1-5-21-1362911470-1944611129-2500288337-1131', Networkdomain = 'DOMAIN', networkalias = 'jondoe' 
    where id = 'admin'
-- AXPRODBA --> AOS service account
update userinfo set SID='S-1-5-21-1362911470-1944611129-2500288337-1133', Networkdomain = 'DOMAIN', networkalias = 'AXPROAOS',  NAME = 'AXPRODBAOS'    
    where id = 'oldaxprodba'
-- Workflow account
--update userinfo set SID='S-1-5-21-1362911470-1944611129-2500288337-1132', Networkdomain = 'DOMAIN.INT', networkalias = 'AXPROCON', NAME = 'AXPROCON'
--    where id = 'wfexc'

--Setting Database Permissions for the AOS service account.  Will already be set if you have started the AOS service.
--select * from sysServerSessions  --AOSAccount
update sysServerSessions 
    set AOSID = 'SRV01@2712',
        AOSACCOUNT = 'DOMAIN\AXPROAOS'
        --, WORKLOAD = '11811151'
    where SERVERID = '1' AND AOSID = 'SRV02@2712'
--The recommended approach would be to remove all records from the sysserversessions table while there are no AOS instances running and have the record recreated as the AOS service starts.
delete from sysServerSessions
*/

-- Workflow
-- Run the Workflow infrastructure configuration again to rebuild the jobs?
Print '>> Workflow'
select * from BATCHJOB where CAPTION like 'workflow%'
select * from BATCH where CAPTION like 'workflow%'
/*
-- Already updated the Batch.SERVERID value, above
*/

-- SysFileStoreParameters Document
print '>> SysFileStoreParameters Document'
select * from SysFileStoreParameters
/*
-- update file store directory?
--update SysFileStoreParameters set FILEPATH = '' where KEY_ = 0
*/

-- Email params
Print '>> Email params'
select * from SysEmailParameters
select * from SysEmailSMTPPassword
/*
-- SysEmailParameters
--update SysEmailParameters set SMTPRELAYSERVERNAME = 'smtp.gmail.com', 
-- SMTPPORTNUMBER = '465', SMTPUSERNAME = 'TEST@gmail.com'
-- where KEY = 0
-- password is encoded, and too long to insert here
--update SysEmailSMTPPassword set PASSWORD = '', AOSID = 'SRV01@2712'
--  where AOSID = 'SRV02@2712'
*/

-- Enterprise Portal WebSiteParams
print '>> Enterprise Portal WebSiteParams'
select * from EPWebSiteParameters
select * from EPGLOBALPARAMETERS
--select * from EPDOCUPARAMETERS
--select * from EPPERSONALIZE
select * from COLLABSITEPARAMETERS
/*
update EPWebSiteParameters 
    set INTERNALURL = 'http://SRV01/sites/DynamicsAx'
    , SITEID = '835C2EE4-CBB9-4D6A-8CD6-FE0BD5F2ED51'
    , EXTERNALURL = 'http://SRV01/sites/DynamicsAx' 
    where COMPANYID = 'DAT'
    
update EPGLOBALPARAMETERS 
    set HOMEPAGESITEID = '835C2EE4-CBB9-4D6A-8CD6-FE0BD5F2ED51'
    where HOMEPAGESITEID = 'C73610FD-C4CE-4AA7-A501-007B4D8E1BC0'
update EPGLOBALPARAMETERS 
    set DEVELOPMENTSITEID = '835C2EE4-CBB9-4D6A-8CD6-FE0BD5F2ED51'
    , SEARCHSERVERURL = 'http://SRV01/sites/DynamicsAxClientSearch/_vti_bin/search.asmx'
    where HOMEPAGESITEID = '835C2EE4-CBB9-4D6A-8CD6-FE0BD5F2ED51'

update COLLABSITEPARAMETERS 
    set ROOTURL = 'http://SRV01/sites/DynamicsAx'
    where ROOTURL = 'http://SRV02/sites/DynamicsAx'
*/

-- DMF (Import/Export Framework)
select * from DMFParameters
select ds.*, dsp.*
  from DMFDATASOURCE ds
    inner join DMFDATASOURCEPROPERTIES dsp on dsp.SOURCE = ds.SOURCENAME
/*
update DMFParameters 
 set SHAREDFOLDERPATH = '\\SRV01\dmf\'
 --, VALIDATIONSTATUS = 0 -- Juuuust in case
 where KEY_ = 0
-- TODO: Recreate file-formats manually
*/

-- Project Server Integration
Print '>> Project Server Integration'
select * from ProjServerSettings
select * from SyncParameters
/*
-- TODO: Update
*/

-- Fix form cache problems, requires an AOS restart.  Not necessary if Ax Client only ever 'points' to one AX instance
select * from SysSQMSettings 
/*
update SysSQMSettings set GLOBALGUID = '00000000-0000-0000-0000-000000000000'
*/

Use at your own risk... But at least I can get the AOS up and running again now.

miércoles, 24 de julio de 2013

AX 2012 SSRS error (rsAccessDenied)


Error while setting server report parameters. Error message: The permissions granted to user 'DOMAIN\user' are insufficient for performing this operation. (rsAccessDenied)
This is a well documented error [1], [2] but this happens all of the time.

1. Open IE on the Reporting Server, with Run as Administator
2. Lets go to http://localhost/reports

3. Select the DynamicsAx installation folder, then Properties, New Role Assignment
Add your AX domain user group or user

4. Check all the checkboxes; Browser, Dynamics Ax Browser, Content Manager, My Reports, Publisher, Report Builder.  This is for a development profile.  Be more restrictive for the production environment.
Click OK.
Format: DOMAIN\AXUserGroup
We now have the users added, and there is no need to restart the services to see the changes.

viernes, 19 de julio de 2013

Unknown source for data method CrmIntegrationStatus. The method does not exist in the data source or table.

Error. Applying AX 2012, CU6 to an AX 2012 CU1 instance,  the following error was generated after compilation:

Unknown source for data method CrmIntegrationStatus. The method does not exist in the data source or table.
Also, we found the following items created in the USR layer?!



Solution: Create the following method in the SalesQuotationProjTable:

// Fix to allow compile of SalesQuotationProjTable form
display NoYes CrmIntegrationStatus()
{
    return NoYes::No;
}

Yuck!

Comments to resolve the problem properly most welcome.  In this case new functionality was added with this new version regarding a Microsoft CRM integration, that our client would not be requiring, and perhaps our method should be throwing an 'unimplemented' error.

jueves, 23 de mayo de 2013

createrecidindex

I find myself using the createrecidindex property more and more on my tables in AX 2009, perhaps due to my growing experience with the AX 2012 product.  One small omission from the table properties documentation in the MSDN is the actual name of the index - RecId.

static EVE_NewsTemplate find(RefRecId _refRecId, boolean _forUpdate = false)
{
    EVE_NewsTemplate      tbl;
    ;

    if (_refRecId > 0)
    {
        tbl.selectForUpdate(_forUpdate);

        select firstOnly tbl
            index hint RecId
            where tbl.RecId == _refRecId;
    }

    return tbl;
}

Reading the AX 2012 best practices it seems to indicate that there is always an index created on the RecId field.