Microsoft Dynamics AX 2012 Enterprise Portal Performance Tips

Role Centers

  1. Cues - Make sure the Queries used by Cues has indexes on the fields used in the ranges.
  2. Cues- Do not have more than 6 cues in one role center page
  3. Reports/Charts - Do not have more than 2 reports or charts in a role center page
  4. UnifiedWorklist – Make sure old records in EventInBox , WorkflowWorkItemTable,  smmActivities are periodically archived and removed from the production database.

List Page


  1. You can control the page size of all list pages installation wide from System Administration > Setup >Enterprise Portal > Enterprise Portal Parameters > General > Number of rows to display in list pages. After making a change, make sure the cache is cleared in Enterprise Portal for this setting to take effect. 
  2. Do not display more than 20 records in one page in a list page.
  3. Use Display Methods in grid with caution. They are evaluated for every row and are generally time consuming. If you need to display calculated values, then have them displayed in a fact box or in a preview pane, so that it gets calculated only for the selected row and not for all rows returned by the query. Also enable caching on Display Methods.
  4. For the queries used in factboxes/related information make sure they have appropriate indexes
  5. In Factboxes are using expensive quries, delay load it. ( either load asynchronously or make it as a dialog which the user can invoke through action pane when needed)
  6. Do not have more than 8 columns in the grid.
  7. For the factbox/preview pane , do not have more than 5 rows per page in case of grid
  8. For the secondary list pages , make sure appropriate index is there for the fields used in the ranges and sort orders
  9. For polymorphic tables, make sure adhoc mode is set. ( set OnlyFetchActive to yes in Dataset Datasources)
  10. Avoid changing any properties that trigger data binding in the prerender event of the GridView. Instead, do that in the page prerender



  1. Lookups can be marked as Client-side lookup. The data for the first page of the lookup will be fetched when the page is initially rendered. When the user clicks the lookup button, the lookup will be displayed immediately on the client side without going back to the server.
  2. If the lookup is generally small (less than 50 items), marking it as a client-side lookup is recommended.  For that, set the LookupStyle to Preload.If the lookup values do not change (for example currency, state, country, and so on), then set the LookupCacheScope to Global or DataBindingContainer. For example

private void AttachLookupsToBoundFields()


foreach (DataControlField dcf in this.Group_Transaction.DataControlFieldCollection)


          AxBoundField boundField = dcf as AxBoundField;

          if (boundField != null)


                switch (boundField.DataField)


                    case "ExchangeCode":

                        boundField.LookupStyle = LookupStyle.PreLoad;

                        boundField.LookupCacheScope = CacheScope.Global;                     


                    case "PayMethod":

                        boundField.Lookup += new EventHandler<AxLookupEventArgs>(PayMethod_Lookup);

                        boundField.LookupStyle = LookupStyle.PreLoad;

                        boundField.LookupCacheScope = CacheScope.DataBindingContainer; // since CostType is not changing on this page, we can cache it for the form                       







Detail Pages


  1. Cache the values in local variables for multiple code paths are calling, for example getting the current row.
  2. Set the AutoSearch and AutoQuery properties on the Data set data sources if the query is modified through code or through ranges added before the values are used. This will be beneficial mainly for create and edit scenarios where the query is always modified or the result set is not needed (in the case of create).
  3. Write managed code wherever possible for better performance and to avoid going back and forth from managed code to X++ through proxies.
  4. Use GetFieldValue instead of GetField to get the field values in managed code. GetField is on the AxaptaRecord, which is a wrapper around the X++ instance of the record. GetFieldValue is on the DataSetViewRow, which internally looks at the dbCache hooked to the X++ record. Use GetFieldValue whenever you can because then your code will benefit from the perf improvement.
  5. For polymorphic tables, make sure adhoc mode is set. ( set OnlyFetchActive to yes in Dataset Datasources)
  6. Avoid changing any properties that trigger data binding in the prerender event of the GridView. Instead, do that in the page prerender
  7. If you are using AppFabric for storing Server State, then you can also use AppFabric to store any other custom cache that you need for your customizations.

For example

 // Check the state cache

             IAxStateCache stateCache = AxStateCacheFactory.CreateStateCache(this.Page.Session);

             if (stateCache != null)


                 object cachedState = stateCache.LoadState(this.GetExpenseTransToolbarMenuCacheKey());

                  if (cachedState != null)


                      // Got it from the cache - deserialize it

                     this.expenseTransToolbarMenu = WebMenuItemMetadataHierarchicalContainer.Deserialize((byte[])cachedState);




                      // Not found in the cache - create it

                      this.expenseTransToolbarMenu = this.GetExpenseTransToolbarMenu();


                      // Save it in the cache

                      stateCache.SaveState(this.GetExpenseTransToolbarMenuCacheKey(), this.expenseTransToolbarMenu.Serialize());




  1. Minimize the page size as much as possible.  For complex forms, separate header and detail pages and display only the section that’s needed. Use Expense Report page as an example.





  1. Use AppFabric for NLB topology or enable machine affinity.


   <AppFabricCaching Enable=”true” NamedCache=”FooCache” />

</ Microsoft.Dynamics>

  1. Set the MaxSessions in web.config to the maximum concurrent users that you expect for your scenario (taking available memory into account).


 <Session Timeout="15" MaxSessions=”300”/>


  1. Disabling Tracing and Debugging
  2. 4.  Configure IIS compression
  3. 5.  After IISReset or app pool recycling, invoke the EPWarmpup page to cache the metadata http://<server>/sites/dynamicsax/_layouts/ep/EPWarmUp.aspx


UX Patterns

Follow the UX guidelines provided in


Comments (3)

  1. Glen Turnbull says:

    Hi, this is very useful, thanks. How can we best measure / analyse performance of Enterprise Portal processes? (e.g. For AX client processes there is the AX client/server trace, Trace Parser and SQL statement trace log)

  2. Mey says:

    You should be able to use the same set of tools ( trace parser , SQL statemetn trace). Trace parser supports .NET business connector , so all EP calls are also traceable.

  3. Jason says:


    Where do I add the following?


       <AppFabricCaching Enable="true" NamedCache="AX2012" />

       <Session Timeout="15" MaxSessions="100"/>


    You state above in the Configuration section, but never mention where.

    Please advise.

Skip to main content