Thursday 30 August 2018

Setup user relation in Dynamics 365FO / AX 7

How to associate a Person/Worker with a User ID in Dynamics 365
In Microsoft Dynamic AX 2012, a user ID must be associated with a worker to complete task such as approving a journal entry. Similarly, Dynamic 365 will have a user ID associated with a person. After the person is added, do the following steps to associate a User ID with a person.
  • Navigate to: System Administration > Users > Users
  • Find the user ID that needs an associated person. Click the hyperlink user ID.



  • User 'Person' locate the name and click select.

















  • Click 'Save' to save your changes.


  • The user ID is now associated with a person.

Associating a Person/Worker with a User ID in Dynamics 365

How to associate a Person/Worker with a User ID in Dynamics 365
In Microsoft Dynamic AX 2012, a user ID must be associated with a worker to complete task such as approving a journal entry. Similarly, Dynamic 365 will have a user ID associated with a person. After the person is added, do the following steps to associate a User ID with a person.
  • Navigate to: System Administration > Users > Users
  • Find the user ID that needs an associated person. Click the hyperlink user ID.
  • User 'Person' locate the name and click select.
  • Click 'Save' to save your changes.
  • The user ID is now associated with a person.

Tuesday 28 August 2018

Deploy reports in AX 2012

Microsoft Dynamics AX includes many default reports that you must deploy. If you did not deploy the reports when you installed the Microsoft SQL Server Reporting Services extensions, you can deploy them by using Windows PowerShell. The following procedures can help you deploy the reports.

Before you begin

Before you can deploy the reports by using Windows PowerShell, you must complete the following tasks:
  • Verify that Windows PowerShell 2.0 is installed on the computer that you are using.
  • Verify that your Windows domain account is a member of the Administrators group on the server that is running Reporting Services.
    Note
    If your Windows domain account is assigned to a group that is a member of the Administrators group, it may take some time to validate that you are a member of the Administrators group. If you experience a delay when you deploy reports, consider adding your Windows domain account directly to the Administrators group.
  • If Reporting Services is running in native mode, verify that you are assigned to the System Administrator role on the Report Manager website.
  • If Reporting Services is running in SharePoint integrated mode, verify that you have been granted Contribute permission to the document library where you plan to deploy the reports.
    Note
    SharePoint integrated mode is supported if you are using Microsoft Dynamics AX 2012 R2 or later.

Open Windows PowerShell and view a list of reports

Complete the following procedure to open Windows PowerShell and view a list of the reports that are included with Microsoft Dynamics AX.
  1. Open Windows PowerShell as an administrator by following these steps:
    1. Click Start > Administrative Tools.
    2. Right-click the Microsoft Dynamics AX 2012 Management Shell option.
    3. Click Run as administrator.
  2. Retrieve a list of the reports that are included with Microsoft Dynamics AX, and store the list in a local variable by entering the following command:
    PowerShell
    $reports = Get-AXReport -ReportName *
    
    For more information about the Get-AXReport command, see Get-AXReport.
  3. View the list of reports by entering the following command:
    PowerShell
    $reports
    

Filter the list of reports

In the previous procedure, you displayed a list of all the reports that are included with Microsoft Dynamics AX. To modify and filter the list, you can use the following commands:
  • To modify the list so that only the Name and ChangedDate fields are displayed, enter the following command:
    PowerShell
    $reports | Select-Object Name,ChangedDate
    
  • To filter the list so that only specific reports are listed, enter keywords or report names. For example, to filter the list so that only reports that contain the word CustTrans are listed, enter the following command:
    PowerShell
    $reports | Select-Object Name,ChangedDate | Where { $_.Name -like "CustTrans*" }
    

Deploy the reports

After you have retrieved a list of reports, you can deploy the reports. The Publish-AXReport command is used to deploy the reports. The following examples show how to use this command. For more information, see Publish-AXReport.
  • To deploy a specific report, enter the name of the report. For example, to deploy the CustTransList report, enter the following command:
    PowerShell
    Publish-AXReport -ReportName CustTransList
    
  • To deploy two or more specific reports, enter the names of the reports. For example, to deploy the CustTransList and CustTransOpenPerDate reports, enter the following command:
    PowerShell
    Publish-AXReport -ReportName CustTransList, CustTransOpenPerDate
    
  • To deploy all reports, enter the following command:
    PowerShell
    Publish-AXReport –ReportName *
    

Redeploy the reports

If you have modified a report’s data source or parameters, you must redeploy the report in order for the changes to take effect. To redeploy a report, follow the previous procedures in this topic.
After you redeploy a report, complete the following tasks.

Restart the Reporting Services service

If you’re running Reporting Services 2008 (in either native or SharePoint integrated mode) or Reporting Services 2012 or 2014 in native mode, restart the service by following these steps:
  1. Click Start > Administrative Tools > Services to open the Services management console.
  2. Right-click the SQL Server Reporting Services service and choose Restart.
If you’re running Reporting Services 2012 or 2014 in SharePoint integrated mode, restart the service by following these steps:
  1. Go to the SharePoint Central Administration site.
  2. Click System Settings > Manage services on server.
  3. Stop the SQL Server Reporting Services service.
  4. Start the SQL Server Reporting Services service.

Refresh the AOD cache

Complete the following steps to refresh the application object directory (AOD) cache. This will clear cached application object information for all items in the application object tree (AOT) of Microsoft Dynamics AX.
  1. Open the Microsoft Dynamics AX client.
  2. Open the development workspace.
  3. Click Tools > Caches > Refresh elements.
    After the cache has been cleared, the Infolog displays a message indicating that AOD elements have been refreshed.

Instruct users to delete usage data

Instruct Microsoft Dynamics AX users to delete usage data. Selections that users make while Microsoft Dynamics AX is running are saved as usage data. This data is used to improve the users’ experiences the next time that they run Microsoft Dynamics AX.
Instruct users to delete usage data by following these steps:
  1. Open the Microsoft Dynamics AX client.
  2. Click File > Tools > Options. The Options form is displayed.
  3. Click Usage data.
  4. On the General tab, click Reset.

Extension of classes, tables and forms in D365FO/AX 7.0


First method is of course the legacy method of creating a derived class which we want to extend, adding or overriding base methods in it and use this class in our new model instead of the base class. This solves many of the customization work we need but there might be cases this method is not desirable or we cannot modify the code of existing tables and forms like that.
Second option is to create something new called an ‘extension class’ to extend the program code of an existing object. This is simply done by creating an extension class with the template shown below using the ‘ExtensionOf’ attribute:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[ExtensionOf(classStr(MyClass))]
final class MyClass_Extension
{
private int myParm;
private void new()
{
}

public int parmMyParm(int _myParm = myParm)
{
myparm = _myParm;
return myParm;
}

public static MyClass constructFromMyParm(int _myParm)
{
MyClass myClass;

myClass = new MyClass();
myClass.parmMyParm(_myParm);
return myClass;
}
}
This way you can add new methods, variables, constructors and static methods directly added to the base class instead of using a derived class. After this, you can call the new methods and constructors you have added in your extension class directly from the base class itself, such as:
MyClass::constructFromMyParm(24).
The suffix of the extension class you have created must be ‘_Extension’ and you can name the MyClass part with anything you want, it does not have to be the base class name. Same way you can create code extensions for tables and forms (as of version update2) as well, later we will try an example with each.
Although this looks like a derived class construction, the extension class is not a derived class from the base and you cannot access private and protected methods and variables, nor override existing methods of the base class here. But it is possible to access public methods and variables of the base class as well as using ‘this’ keyword in your method declarations to access those. It is also possible to access the methods of other extensions on the same base object if you have added the model that includes the other extension class in your model definition’s referenced packages.
I also want to mention the extension class template below. Before the “Update1” version of AX7, the template for creating the extension class for tables and classes was like below :
1
2
3
4
5
6
7
8
public static class MyClass_Extension
{
public static int parmMyParm(MyClass _this, int _myParm = myParm)
{
myparm = _myParm;
return myParm;
}
}
Here you declare your class and all the class methods as static (class with _Extension suffix) and add the object you want to extend as the first parameter of your method. I do not recommend using this template in your new program code because the new one is more readable and useful, but be aware: On runtime your new notation extension class works exactly the same way using static method calls, just like the old notation did. This is why you cannot access class private and protected variables nor override existing methods in it. Also for the same reason you should not create a direct instance of the extension class in your program code, nor create another class derived from your extension class (it also receives a “sealed” attribute when built into CIL, like other static classes in .net). You can confirm it for yourself using visual studio debugger:
Capture11
Capture12
Creating table methods is pretty the same, you can even create new display and edit methods as shown below, to be used in a form (or form extension) in the same model :
1
2
3
4
5
6
7
8
9
10
11
12
13
[ExtensionOf(tableStr(InventTable))]
final class ExtensionDemo_Extension
{
private void new()
{}

[SysClientCacheDataMethodAttribute(true)]
public display Description dispExtendedDesc()
{
return this.Description5+this.Description6;
}

}
To be able to use this display method in your form, you need to define the “Data method” property of your data field like this, using static method operator and name of your extension class (“ExtensionDemo_Extension::dispExtendedDesc”). Directly writing the method name will not work :
Capture6
Form extensions are created pretty much the same way. The newly added methods are accessible from the form and its extensions. The ‘this’ object in your extension contains the element object (FormRun) of the extended form, so you can query for elements and data sources easily from here. Here is an example how to use element variables in a form extension class in various different ways :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[ExtensionOf( formstr( ExtensionDemoForm ))]
final class ExtensionDemoForm_Extension
{
 private boolean hasArgs;

 private void new()
 {}

 public boolean parmHasArgs(boolean _hasArgs = hasArgs)
 {
 hasArgs = _hasArgs;
 return hasArgs;
 }

 public boolean hasArgsRecord()
 {
 return (this.args().record()!=null);
 }

 [FormEventHandler(formStr(ExtensionDemoForm), FormEventType::Initialized)]
 public void ExtensionDemoForm_OnInitialized(xFormRun sender, FormEventArgs e)
 {
 this.parmHasArgs((this.args()!=null));
 }

}
Note that the event handler here does not have the ‘static’ keyword, but instead declared as a class instance method intentionally removing the static keyword from the definition. It is possible to declare some of the event handlers like that then you can use ‘this’ keyword to access methods and variables defined in the same class from a eventhandler (more on eventhandlers on Part3).
You can add a simple click method and test our extension method inside the form :

public void clicked()
{
super();
info(strFmt("Has args?: %1", element.parmHasArgs()));
info(strFmt("Has args record?: %1", element.hasArgsRecord()));
}


Capture7
Eventually it is also possible to override form control and data field methods from the form extension class, which gives you much more flexibility in creating extensions for forms:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[ExtensionOf( formstr( ExtensionDemoForm ))]
public final class ExtensionDemoForm_Extension
{
public void clickedOverride()
{
info(strFmt("Name : %1", this.name()));
}

[FormEventHandler(formStr(ExtensionDemoForm), FormEventType::Initialized)]
public void ExtensionDemoForm_OnInitialized(xFormRun sender, FormEventArgs e)
{
FormButtonControl button = this.design().controlName(formControlStr(ExtensionDemoForm,FormButtonControl1));

button.registerOverrideMethod(methodStr(FormButtonControl,clicked),'clickedOverride', this);
}
}
A note on form class extensions: In this time of writing (Update 3 version), not everything with form class extensions work all right, it has some bugs which are already reported to Microsoft. For example the code above compiles ok but on runtime the method above is not accesible from the Formrun class, although the previous example compiles and runs just fine (just using ‘this’ keyword in the same class). I will post an update if things change in the future on that part.
Plugins
Plugins are yet another way to extend code in new AX7 besides the extension methods we mentioned above. Plugins use attributes to create new subclasses and subclass methods which can be used as alternatives to existing classes and methods belonging to same plugin base and can be initialized using a string type of key from the SysPluginFactory class. This way you can also choose which plugin to use by selecting it with a string parameter. I will not get into the details of using plugins and the attributes used in plugin framework but perhaps I might write another blog about them in the future.


Adding a newline into a string in C# and X++

Below is the sample code we can use for  adding a newline after every occurrence of "@" symbol in the string in C#   using System...