-->

AX 2012 R3 SSRS: publishreportcommand network name cannot be found


SSRS report deployment gives error, "The network name cannot be found."


Audience

Dynamics AX 2012 (FP, R2 R3) X++ Developers, Functional and Technical consultants and advanced users

Background

When deploying a SSRS report, you may come across the error. This error will occur while deploying report(s) through AOT as well as using PowerShell scripts.


Experience tells us that such issues may occur if service accounts (AOS, BC proxy, Workflow) are wrongly configured. In our scenario, we had to reconfigure and put the newly provided service accounts. As a result, the reporting services crashed. We made sure all the practices related to configuring system service accounts are met. However we kept getting this error. report deployment were attempted both using AOT and PowerShell

Solution(s)
Thanks to sharing, the coolest caring. we cam to know the following link that clearly mentioned the reason of this issue.

https://blogs.msdn.microsoft.com/axsupport/2013/03/13/deploying-reports-in-ax2012-you-need-access-to-the-administrative-share-c/ 

In the post, the user uses the verbose modifier in the publish command in PowerShell to get more details. That yields that a network shared location access is attempted by the script. Now the question is, if such access is available or not. As a resolution, providing the C drive (reporting services server) as network shared resource resolved the issue.

Links

AX 2012 Workflow: Function run has been incorrectly called.

maqk® by MAQ Khan | 6:06 PM

AX 2012 Workflow: Function run has been incorrectly called.

Workflow submit ends in error notification when submitting to workflow from code

AX 2012 Workflow: Function run has been incorrectly called.

Audience

Dynamics AX 2012 (FP, R2 R3) X++ Developers, Functional and Technical consultants and advanced users


Background

At the point of submitting a workflow, the comment dilog box appears. The class, is constructed needing a table buffer. The tupple must contain a row for the active workflow. This is usually passed by the statement
args.caller().getActiveWorkflowConfiguration()
The following  listing provides a detailed context

    workflowSubmitDialog = WorkflowSubmitDialog::construct    (args.caller().getActiveWorkflowConfiguration());
    workflowSubmitDialog.run();


Problem

Our working form stopped to resolve a particular configuration for the workflow. This was pretty strange behavior as a lot of records completed different scenarios of the workflow in success. we refreshed AOT items, generated incremental and FULL CIL, restarted the service, cleared the cache, but nothing worked.

Solution(s)

This must be a configuration or framework issue as a working workflow stopped being not able to find a particular version row (which exists in the table). Several investigatory steps were carried as mentioned in the problems section but none resolved the issue.

Alternatives

The solution should be a framework refresh. The only quick alternative for us was to write an alternative i.e fetch the existing version row our self and provide it to the WorkflowSubmitDialog[C] object. We did as follows;

  • Write a custom method in [T]WorkFlowVersion that returns the buffer. The following query does the job
select firstOnly1 *
   from
workflowVersionTblBfr
    join workflowTblBfr
    where
workflowVersionTblBfr.WorkflowTable     == workflowTblBfr.RecId &&
workflowVersionTblBfr.Enabled           == NoYes::Yes           &&
workflowTblBfr.TemplateName             == _wfTemplateName    
        ;
        return workflowVersionTblBfr;
    • Call the new method in the submit method of the WorkFlow SubmitManager class once it is verified that the workflow version is not being fetched by the framework

      Method navigation: Workflow submit manager class > Submit method > add call after workFlowSubmitDialog object is constructed
    //
        if (!workflowSubmitDialog || !workflowSubmitDialog.parmWorkflowConfiguration() )
    workflowSubmitDialog = WorkflowSubmitDialog::construct(WorkflowVersionTable::T4ED_GetWFConfig
    (workFlowTypeStr(T4EDPurchPORecWFType), tableName2id(tableStr(T4EDPOProdRecConfExtWF)), recId
    ));
    //

    Note: Since you are submitting a workflow, you don't need to look for the record specific workflow version. This would be mandatory if we are taking any action on an already submitted record. In such scenario, we will require to search for configurations that exists in WorkflowWorkItem table for specific table and record.


    AX 2012: Invalid application object name error while creating child table fields

    Error message: 

    Invalid name. The application object already exists. 

    Audience

    Dynamics AX 2012 (FP, R2, R3) X++ Developers, Functional and Technical consultants and advanced users


    Background

    Using inheritance in tables, you may receive the subject mentioned error
    "Invalid name. The application object already exists."

    Problem

    This error comes due to the fact that two tables inheriting from the same base table cannot have fields with same name. To avoid such error, you need to put distinct name among each table extending the same base table.

    Reason

    The reason is not any of the object oriented myths :) The simple reason is that, no matter how many levels of abstraction the AOT layer add to schema items like tables, a table among its extending tables exists only once at the database layer (SQL) . This is like that since child tables actually only exists at AOT layer. Physically there is one single base table. The data resides in one table physically which is abstracted at AOT as child tables.

    That means, if you have a base table with 100 child tables, there would be only one physical table for all of them at the database layer. For this reason, you cannot have same name field(s) for different child tables extending same base table.

    Conclusion

    Keep each child table's field names distinct among all sibling tables.

    AX 2012: You are not authorized to access table ‘’ (). Contact your system administrator.

    Audience

    Dynamics AX 2012 (FP, R2 R3) X++ Developers, Functional and Technical consultants and advanced users


    Background

    You may experience the subject mentioned error while opening a table / view

    Problem

    I experienced this error while creating a new view. When I accessed it to see if it is working as expected, I received this error.




    I carefully examined and found that actually no fields are added into the view.


    Solution(s)

    At this point of time, every one knows the solution, add some field dude. Adding fields to the view solves the error. However this error is quite distracting as it can take you to an American Wild Goose chase i.e. towards security and authorization implementations. so keep googling before diving straight into the deep AX sea :P


    AX 2012 - Understanding AOT Maps with an example

    maqk® by MAQ Khan | 7:17 PM

    Understanding AOT Maps with an example

    Subject: AOT Maps

    Audience: Dynamics AX Developers

    Background

    Maps are not new concept in software development actually. They are table wrappers to achieve general behavior. However for lame dude(s) like me, these definition words have not been enough.

    Problem

    The term allotted to Maps, "Map" itself is a bit confusing. But an example can really help understanding. And Maps are used everywhere, but in comparison to tables and classes ( see these building blocks are essential for any kind of most basic development), use of maps are quite rare.

    Example

    I have been browsing PurchTableHistory table. A method came into my consideration where I see the use of Map.  

    The method, PurchTableHistory[T] >> initFromPurchTable() declares several maps based on localized buffers. Look at the following code

    // Code example

    PurchTableMap purchTableMap;
    purchTableMap.data(_purchTable.data());
    this.data(purchTableMap.data());
    First, the row from PurchTable is copied to the map variable, 'purchTableMap', and then, the history buffer gets the same row but form map, and not from the original source, purchTable buffer

    WHY ? Their must be a genuine need ? Why don't we copy from the original PurchTable buffer  ? Becuase we cannot :) becuase of schema change. See if most of the fields are same but not with exact field names, types and filed list count, we cannot copy a row from one table to another using xRecord[C].data() simply because of schema mismatch.

    Here is where map can work, since the different name same type and purpose fields are MAPPED in the MAP :). Fields with different names from different tables are mapped to consistent names in map, so that you can use them to map one row ( from one table buffer) to another table.

    Updated: Rephrasing the above in other words, map can be used to manipulate common schema among different (and having entirely different schema ) tables. It is like not knowing a buffer at runtime, expecting from it to be implementing a consistent schema with labelling issu

    One more thing, when using maps,
    field count doesn't matter since the map will only care and execute on the schema defined in the map. It simply would not care for schema defined in the mapped tables, it would only care for the schema defined in the MAP

    Happy MAPPING

    Links

    AX 2012 - Define items of a combo box at design time

    maqk® by MAQ Khan | 11:27 AM

    Combo box in AX 2012

    Background

    There are numerous ways to load values into a combo box in AX forms. The most common is to use base enums. One way is to use sysTableLookup to load master table data. Another way is to load another form at lookup event and interchange values using args. However sometimes its convenient to define custom items at design time. And such a thing is not very obvious in AX IDE. I recently discovered while answering an AX community post that HcmWorkerLookup form has an other way to do the same.

    We all as ASP.Net developers know that we use to define the members of a ComboBox control. There is a similar way to do the same in AX as well. This is useful if your combo box has small no of items in it which are static, unchangeable values and are not suppose to update

    Problem

    When you have few static options to provide to user and for some reason, you want to show the user control as a combo box, you better define those few options at design time.

    Solution(s)

    I love AX due to the rapid development engine and reusable frameworks. AX provides the solution to the above problem definition by providing enough properties to define all the members / items under a combo box control. The ComboBoxControl has three properties which will be used.

    You will have to focus on 3 properties on the combo box control. 

    1. Items It is the number of items (count) to appear on the combo at run time.
    2. Item  -  It is the currently selected item at design time, the following property works on the currently selected item
    3. Text -  It is the name or caption to appear for the currently selected item (number entered in Item property)

    So how will you design it  ? E.g. you want three items to appear in your combo with values defined at design time and without involving any BaseEnum or table values or EDT relation. For three items, you will set the Items property of combo to 3. Then, to define the text values for each item, you will have to repeatedly update the Item property ( current item ) to 1,2, 3 and provide text value for each in the Text property.

    Try it, its not cool may be, but knowing this IS COOL for sure ;)

    Links

    • https://community.dynamics.com/ax/f/33/t/179483  

    AX 2012 R3 - Customising the Purchasing Policies

    maqk® by MAQ Khan | 11:48 PM


    This document provides a tutorial to customize the purchase order generation policy. Knowledge shared here can be used to gain a hands on idea to customize the PO generation policy as well as to get a similar idea about other policies coming under the umbrella of purchasing policy like requisition purpose rule and replenishment control rule etc.

    ENTRY POINT:

    Workflow (PurchReqReview) class,  completion event.

    FLOW:

    At each status method, namely started, cancelled and completed, helper class static methods are called.

    Class: PurchReqWFStatusTransitionHelper

    As the name suggests, the class responsibility is to run seperate and specific logic per PurchReq. There is a method foe each status like In review, Draft, Approved etc.
    At (C), at method for the status, "completed",, the following line is called
    PurchReqWFStatusTransitionHelper::setPurchReqTable2Approved
    (_workflowEventArgs.parmWorkflowContext().parmRecId());
    
    This method in its body calls for logic which first update each PurchReqLine flag after considering the configured Purch Req policy. Then it calls code to generate PO for all PurchReqLines of purpose. See code below:
    RequisitionReleaseStrategy::updateManaulDocumentGeneration
    (_purchReqTableRecId);
    purchReqWFStatusTransitionHelper.doVersioning
    
    (_purchReqTableRecId);
    
    if (purchReqTable.RequisitionPurpose == RequisitionPurpose::Consumption)
    {
    PurchReqPurchaseOrderGenerationInSync::run(purchReqTable);
    }
    

    System Querying PurchReq PO generation policy

    As per above, (C)ReleaseStrategy >> method  is called. This method updates each line field  based on query policy data read from DB. It is this flag field in each line in the end that ensures if the PO from this line is to be generated manually or automatically

    HOW IS POLICY DATA READ FOR EACH PR LINE ?

    RequisitionREleaseStrategy calls the boolean returning method in a conditional check to evaluate at runtime if the purchReqLIne field  be set to true or not. Consider the following line of code:
    PurchReqPurchaseOrderGenerationRule::
    isManualCreatePurchaseOrderStatic(purchReqLine)
    
    if (!purchReqLine.VendAccount || 
        PurchReqPurchaseOrderGenerationRule::
    isManualCreatePurchaseOrderStatic(purchReqLine))
    {
        purchReqLine.IsPurchaseOrderGenerationManual = true;
        purchReqLine.update(false);
    }
    
    
    PurchReqPurchaseOrderGenerationRule::
    isManualCreatePurchaseOrderStatic() 
    
    inits the class object, sets PurchReqLine buffer via parm method, initializes the policy (abstract from us, not in scope of the topic), and calss the instance method <>. See code below
    PurchReqPurchaseOrderGenerationRulepurchReqPurchaseOrderGenerationRule;
    
    purchReqPurchaseOrderGenerationRule = PurchReqPurchaseOrderGenerationRule::construct();
    purchReqPurchaseOrderGenerationRule.parmPurchReqLine(_purchReqLine);
    purchReqPurchaseOrderGenerationRule.initPolicy();
    
    return purchReqPurchaseOrderGenerationRule.
    isManualCreatePurchaseOrder();
    
    The method then checks the line against the policy and returns a boolean, true for manual PO creation, false for auto.

    Customizing the PO Generation Policy

    isManualCreatePurchaseOrder method can be read to get an idea how to customize this policy to add custom fields and conditional checks and extend the logic to evaluate if PO from PR (WorkFlow) should be generated or not.
    After reading the simple method, we come to the points as follows;
    • The PO generation policy form is binded with table:
    • The Table has 5 NoYes enum fields which are rendered on the PO generation policy config form as radio hierarchied buttons
    • These fields are evaluated in the (C)PurchReqPurchaseOrderGenerationRule. isManualCreatePurchaseOrder() method.
    • To add custom evaluation logic, you can add a field, a relation, or an instanceRelation extension to this table write valid evaluation code for the new schema in the aforementioned method.
    HAPPY PR TO PO GENERATION POLICY EXTENSION

    Valid length of a form field label

    maqk® by MAQ Khan | 3:34 AM

    AX sometimes surprise you. Such surprise often make you chase a wild goes all day to reveal it was just a dead rat :@

    This just happened with me but all to reveal something I don;t think would be available on internet

    Try these:

    1. Find or create a label with 250+ length. 
    2. Assign this label to a form field (not static field or any such control)
    3. Open that form
    4. Your client just crashed
    Why am I telling this to you at all is the fact that my client wanted me to put huge texts against form fields. Weird, but sometimes we face requirements about which client donot accept any consultancy or education, and we just HAVE to implement it.

    Now can you imagine how wild those 400+ length labels made me work and search and find the clue why my client is crashing. I went through everything including full compile, sync, cache cleanup, .auc files, label file regeneration. I had to take every step due to the reason that evenvwr log was not much of a help in my scenario. I am attaching the log for your reference here;


    Application: Ax32.exe

    Framework Version: v4.0.30319
    Description: The process was terminated due to an unhandled exception.
    Exception Info: System.AccessViolationException
    Stack:
       at Microsoft.Dynamics.Kernel.Client.ActionPaneInterop.ClickEventHelper.Clicked(System.Object, System.EventArgs)
       at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionItem.OnButtonClick()
       at Microsoft.Dynamics.Framework.UI.WinForms.Controls.ActionButton.OnMouseUp(System.Windows.Forms.MouseEventArgs)
       at System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
       at System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
       at System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
       at System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
       at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
       at ._wWinMainCRTStartup()


    Conclusion
    Length for a field label (non static text control) is 250
    Just resolved a basic error with my functional team mate Qamar Zaman Khan. We both were online, Qamar for reproducing the error. Basically our cube processing was failing with the error, 

    OLE DB or ODBC error: Login failed for user 'Domain\UserName$'.; 28000

    I checked the cube and it had the wrong impersonation settings. I googled and found the issue hence echoing the same to all :D

    http://stackoverflow.com/questions/18702987/olede-error-login-failed-for-user-domain-computername-28000  

    In my case, the sql server analysis service login account was set local account which I think is not a good practice. And as default, the impersonation account is set to service account. Due to this, the impersonation was not working since local account (rendered as Domain\) did not had the required accounts on sql as a login. I provided a sql domain account and the error dissappeared :D. Snapshots for your reference





    top