Sunday, October 30, 2011

Increase performance of workflow process in AX 2009 / delete obsolete workflow data in AX 2009

Hi Folks,

Recently, For a customer, I have observed that the workflow processing has become very slow then when i have observed the workflow batch job history, I have found that there are many errors and it says "The company 'tst' does not exist". But this company has been deleted long back.

As we know, In AX 2009, If a company is deleted then all the records with respect to that company will be deleted except the records in the Workflow tables(WorkflowTrackingTable, WorkflowTrackingStatusTable, WorkflowMessageTable). These records have to be deleted via SQL, If these records are not deleted then every time when the workflow batch job is running then everytime it checks those obsolete records too and hence the performance of workflow processing is reduced, because the workflow batch job will always tries to process those obsolete records.

Remember to run the following queries in SQL, if you have deleted a company which has workflow records. This would definitely increase the Workflow performance.


delete from WorkflowTrackingTable where WorkflowTrackingTable.CONTEXTCOMPANYID == 'TST' 

delete from WorkflowTrackingStatusTable where WorkflowTrackingStatusTable.CONTEXTCOMPANYID == 'TST'

delete from workflowmessagetable where workflowmessagetable.WORKFLOWCONTEXTCOMPANYID == 'TST'

Happy DAxing..............

Tuesday, October 4, 2011

Get previous page selected record(context) in EP page in AX 2009

Hi All,

If you would like to get the previous page's selected record (Context) in EP in AX 2009 then you can use the following method in visual studio for it.


AxTableContext context = AxBaseWebPart.GetWebpart(this).ExternalContext;
if (context != null && context.TableId == TableMetadata.TableNum(AxBaseWebPart.GetWebpart(this).Session, "MainTable"))
        {
             string TestField = context.DataKey.GetRecord(this.AxSession).GetField("TestField").ToString();
        }
        

Saturday, October 1, 2011

Workflow validation error in AX 2009: The request failed with HTTP status 405: Method Not Allowed.

When you try to validate the Workflow URL, you might get an error saying "The request failed with HTTP status 405: Method Not Allowed."

To resolve this error , there are two ways :

If your system configuration is

1. Windows 2008 R2 64 bit.

2. SQL Server 2008
3. IIS 7

To resolve this error, the simple solution would be to set your IIS application Pool’s 32bit property to true
1. IIS –>Application pool of WF–> rightclick advanced settings and change 32 bit to TRUE.
2. Reset IIS.

If the above resolution doesn't work then follow the following steps.

This can occur because of the conflict in the Windows between the .NET framework 2.0 and .NET framework 4.0.

So, the following steps might resolve the issue

1. Deleted the application(MicrosoftDynamicsAXWorkflow50) from the Workflow website in IIS
2. Right click on the same workflow site and click on  “ Add a new Virtual Directory” with the same name of the deleted application(MicrosoftDynamicsAXWorkflow50).
3. In the physical path of the virtual directory, Point to the installed workfLow folder (most probably it will be in “C:Program FilesMicrosoft Dynamics AX50Workflow“). This folder contains the web services of AX workflow.
4. convert the “Virtual Directory” to “Application” by right-clicking that directory and clicking “Convert to Application”.

5. Go to permissions of that application,  by clicking ”Authentication” and ensure that "Anonymous" and “Windows Authentication” is enabled and any other things are disabled.
6. Go to the “Handler Mapping” of the Workflow Application. Select “WebServiceHandlerFactory-ISAPI-2.0″ and then click “Edit”. Please check whether the path is pointing to the .NET framework version 2.0 32-bit.  Point to the “aspnet_isapi.dll” file in the Framework folder.
7. Reset IIS and validate the URL again.
 
This resolves your issue and thus the URL is validated.

Happy Axing...........

Cannot submit a timesheet on the Enterprise Portal(EP) website in Microsoft Dynamics AX 2009

Hi All,

The user can create a timesheet but cannot submit a timesheet on the Enterprise Portal website, as the Submit button is not available. To be able to submit the timesheet, you have to go to the previous page of Timesheet List and then reopen the timesheet, then the Submit button appears. However, the Submit button should be available throughout timesheet entry.

As usual, I started googling for some hotfix then I found a hotfix, http://support.microsoft.com/kb/2242554 .
But this is for Timesheet Installed on the PSA Module which doesn't suit my requirement because our customer's application is with Timesheet Installed on the Projects Module then I had to edit the standard eP page and fix the issue myself.

The following will fix the issue.
The changed/extra lines of code is higlighted in Red in the following code.

Please change the following code in TSTimeSheetEdit WebControl.

protected void Page_Init(object sender, EventArgs e)


{

      InitEditableStatus(FormMode);



     // If the report isn't editable then we can skip some initialization

     if (reportEditable)

    {

        InitProjectButton();

           InitFilterTypeSelection();

AxGridViewTimesheetEditLines.RowUpdating += AxGridViewTimesheetEditLines_RowUpdating;

AxGridViewTimesheetEditLines.RowUpdated += AxGridViewTimesheetEditLines_RowUpdated;

AxGridViewTimesheetEditLines.RowDeleting += AxGridViewTimesheetEditLines_RowDeleting;

AxGridViewTimesheetEditLines.RowDeleted += AxGridViewTimesheetEditLines_RowDeleted;

AxGridViewTimesheetEditLines.RowEditing += AxGridViewTimesheetEditLines_RowEditing;



if (FormMode != ApplicationProxy.EPFormAction.CreateMode)

{

using (

IAxaptaRecordAdapter tsTimesheetTable =

ApplicationProxy.TSTimesheetTable.find(AxSession.AxaptaAdapter, TimesheetNbr))

{

if ((ApplicationProxy.TSAppStatus)tsTimesheetTable.GetField(SApprovalStatus) ==

ApplicationProxy.TSAppStatus.Returned)

{

// PanelProject.Visible = false;

}

}

}

}



InitPrintButton();



AxGridViewTimesheetEditOverview.SelectedIndexChanged += AxGridViewTimesheetEditOverview_SelectedIndexChanged;

AxGridViewTimesheetEditOverview.RowDataBound += AxGridViewTimesheetEditOverview_RowDataBound;

AxGridViewTimesheetEditOverview.PreRender += AxGridViewTimesheetEditOverview_PreRender;



AxGridViewTimesheetEditLines.RowDataBound += AxGridViewTimesheetEditLines_RowDataBound;

AxGridViewTimesheetEditLines.RowCommand += AxGridViewTimesheetEditLines_RowCommand;

AxGridViewTimesheetEditLines.PreRender += AxGridViewTimesheetEditLines_PreRender;



#region Workflow related

string fromApprove = Request.QueryString.Get(SFromApprove);



if (null != fromApprove)

{

WorkflowActionBar.Visible = false;

}

else

{

AxDataSourceWorkflowTimesheetEntry.CreatingDataSetRun += AxDataSourceWorkflowTimesheetEntry_CreatingDataSetRun;  // This is the change , Remove the comments for this line

WorkflowActionBar.EvaluatingCanSubmitToWorkflow += WorkflowActionBar_EvaluatingCanSubmitToWorkflow;

WorkflowActionBar.WorkflowSubmitCompleted += WorkflowActionBar_WorkflowSubmitCompleted;

WorkflowActionBar.WorkflowConfigurationLoading += WorkflowActionBar_WorkflowConfigurationLoading;

// MS: WorkflowActionBar.Visible = true;



if (ApprovalLevel == ApplicationProxy.TSApprovalLevel.LineItem) // Line Item Approval

{

WorkflowActionBar.DataSourceID = DsTimesheetEditLines;

WorkflowActionBar.DataMember = DmTSTimesheetLineCurrent;

}

else

{
 WorkflowActionBar.DataSourceID = DsTSWorkflowTimesheetEntry;
WorkflowActionBar.DataMember = DmTSTimesheetTableCurrent;
}
}
#endregion



#region Project Lookup related
AxLookupProjId.Lookup += AxLookupProjId_Lookup;
AxLookupProjId.OkClicked += AxLookupProjId_OkClicked;
#endregion
}

void AxDataSourceWorkflowTimesheetEntry_CreatingDataSetRun(object sender, CreatingDataSetRunEventArgs e)
{

if (TimesheetNbr != null) //Remove the comments

          e.DataSetRunArgs.parm = TimesheetNbr;//Remove the comments
}

#endregion



private IAxaptaRecordAdapter CurrentTimesheet

{

get

{

//return AxDataSourceTimesheetEditOverview.GetDataSet().DataSetViews[AxGridViewTimesheetEditOverview.DataMember].GetCurrent();

return ApplicationProxy.TSTimesheetTable.find(AxSession.AxaptaAdapter, TimesheetNbr);

}

}






private ApplicationProxy.TSAppStatus CurrentTimesheetStatus


{
get

{

ApplicationProxy.TSAppStatus timesheetStatus = (ApplicationProxy.TSAppStatus)CurrentTimesheet.GetField(SApprovalStatus);

return timesheetStatus;

}

}