Monday 30 March 2015

Generating the outbound xml file for all records using File system adapater in ax 2012 AIF

1. Generating the outbound xml file for selected record or single record - using document service(file system adapter).
2. Generating the outbound xml file for all records( i.e. specified criteria on the query) - using document service(file system adapter).

Example: Generating the outbound xml file for selected record or single record.
Below is the code to generate the outbound xml file for the selected record.
static void GenerateXmlSelectedRecord(Args _args)
{
    AxdSendContext      axdSendContext  = AxdSendContext::construct();
    AifEntityKey        aifEntityKey    = AifEntityKey::construct();
    AifEntityKeyList    aifEntityKeyList = AifEntityKeyList::construct();
    Map                 keyData;
    AifConstraintList   aifConstraintList   = new AifConstraintList();
    AifConstraint       aifConstraint       = new AifConstraint();
    CustTable           custTable;
    int i,j;
    CustCustomerService CustCustomerService = CustCustomerService::construct();
    ;
    custTable = CustTable::find('Cust001');

    keyData = SysDictTable::getKeyData(custTable);
    aifEntityKey.parmTableId(custTable.TableId);
    aifEntityKey.parmRecId(custTable.RecId);
    aifEntityKey.parmKeyDataMap(keyData);

    aifEntityKeyList.addEntityKey(aifEntityKey);


    axdSendContext.parmXMLDocPurpose(XMLDocPurpose::Original);
    axdSendContext.parmSecurity(false);


    aifConstraint.parmType(AifConstraintType::NoConstraint) ;
    aifConstraintList.addConstraint(aifConstraint) ;

    info(strFmt("%1",custTable.AccountNum));
    AifSendService::SubmitDefault(  classnum(CustCustomerService),
                                aifEntityKey,
                                aifConstraintList,
                                AifSendMode::Async,
                                axdSendContext.pack());
}

Example: Generating the outbound xml file for all records( i.e. specified criteria on the query).
Below is the code to generate the outbound xml for all the records or specified criteria.

static void GenerateMutiplerecords(Args _args)
{
    CustTable           custTable;
    AxdSendContext      axdSendContext      = AxdSendContext::construct();
    AifEntityKey        aifEntityKey        = AifEntityKey::construct();
    AifConstraintList   aifConstraintList   = new AifConstraintList();
    AifConstraint       aifConstraint       = new AifConstraint();
    AifEndpointList     endpointList;
    AifActionId         actionId;
    Query               query;
    QueryBuildDataSource    qbds;

    query               = new Query(queryStr(AxdCustomer));
    AxdSend::removeChildDs(query);

    actionId            = AifSendService::getDefaultSendAction(classnum(CustCustomerService), AifSendActionType::SendByQuery);
    aifConstraint.parmType(AifConstraintType::NoConstraint);
    aifConstraintList.addConstraint(aifConstraint) ;
    endpointList        = AifSendService::getEligibleEndpoints(actionId, aifConstraintList);

    AifSendService::SubmitFromQuery(actionId,endpointList,query,AifSendMode::Async);
}

Saturday 28 March 2015

Create the batch job in AIF ax 2012

        1.       Open the Batch job form. Click System administration > Inquiries > Batch jobs > Batch jobs.
2.       Create a new batch job.
3.       Set up the following batch job and click the View tasks button.
4.       The Company accounts and Class name fields are mandatory. The Task descriptionHas conditions and Batch group fields are optional but recommended.
5.       Add four tasks that use the following classes to the batch job: AifGatewayReceiveService, AifGatewaySendService, AifInboundProcessingService, andAifOutboundProcessingService.
6.       Set a recurrence interval for the batch job. For testing purposes, it is convenient to set the interval to one minute.
7.       To start the batch job, change its status to Waiting

Run AIF inbound and outbound manually

Here are two jobs to run inbound and outbound messages manually, so you don’t have to wait for the batches to pick them up.
Inbound:
static void KlForrunAIFInbound(Args _args)
{
    ;
    // read the messages
    new AifGateWayReceiveService().run();

    // process the messages in queue
    new AifInboundProcessingService().run();

    info("done");
}
Outbound:
static void KlForrunAIFOutbound(Args _args)
{
    ;
    // process messages in queue
    new AifOutboundProcessingService().run();

    // send messages
    new AifGateWaySendService().run();

    info("done");
}
Ofcourse, you can put this code in classes, or combine them so they are executed together. Because inbound messages can trigger outbound messages, it’s better to process the inbound messages before the outbound messages.
 .

Saturday 21 March 2015

AIF Service Common Usage Scenarios in ax 2012

Custom Services: Use to expose very simple business entities as a service, or to expose custom logic from Microsoft Dynamics AX.
          This Service enables developers to expose any logic written in x++ through a service interface. The support for Custom Services was introduced in Dynamics AX 2009, but it was limited to some specific data types. In Microsoft Dynamics AX 2012 with the integration of Windows Communication Foundation (WCF), attributes can be set on the Data Contract class to make them serialize and De-serialize across the network connection.
·                To expose a custom x++ logic. 
·                Say, you have a custom module and you want to expose some logic/code to your custom application.

Document Services: - Use to expose business entitles with varying degrees of complexity, or to support medium-to-complex integration scenario involving business entities.
                This was introduced in Microsoft Dynamics AX 4.0. It enables the user to exchange data between internal and external systems via XML documents. Document Services are generated from a query that models the business entity. For example, a customer query will run the Document Service Generation Wizard to create the Service artifacts.
Document Services include logic to handle the details of how a query will be serialized or De-serialized from the XML that is sent across a network. For synchronization of Document Services, there are two new entities introduced in Dynamics AX.
§  getKey
§  getChangedKey
Developers need to extend these functions to enable their own scenario.

§  Document services are services which expose a business entity. For example, Customer, Vendor, Employee, Sales Order.
§  You can Map the business entity using Query and run through Document Service Wizard to build the web service and perform CRUD operations.

System Service: System services are Windows Communication Foundation (WCF) services that are included with Microsoft Dynamics AX. These services enable clients to interact with and retrieve system information. 
             This is a new Service category introduced in Microsoft Dynamics AX 2012. This type of Service is not customizable and not mapped to any X++ code. There are three types of Services that come under System Services:
§  Query Service
§  Metadata Service
§  User Session Service
All these Services have unique functionality that will be discussed in my next post.

§  System services are kind of utility services.
§  Up and running when AOS starts.
§  Can be used for interactive clients 
§  Build Ad-hoc query

System Service: Query Service: - Use to implement read operations for any Microsoft Dynamics AX, ad-hoc, or existing AOT query.


  • Enables you to issue a query for data without using an Application Integration Framework (AIF) document service or creating a custom service. The query service returns data in a dataset and implements a paging mechanism so that you can manage queries that return large amounts of data.
When you call the query service, you can specify the query to run in one of three different ways:

    • Static query – A query that is already defined in the AOT under the Queries node.
    • User-defined query – A query that is defined by using the QueryMetadata class which is found in the metadata service.
    • Dynamic query – A query that is defined in an X++ class that extends the AifQueryBuilder class. All query logic resides in the query builder class
System Service: Metadata Service: - Use to retrieve information about the structures in Microsoft Dynamics AX for a client application. For example, if you want to return information about a table such as what indexes exist on that table, you can use the metadata service.

Enables you to retrieve information about elements in the AOT. You can retrieve metadata for labels, menus, menu items, tables, extended data types, data types, enums, queries, web menus, web menu items, info parts, cues, dimensions, form parts, web controls, service groups, and services. The metadata service should be used when you want to return information about the structures in Microsoft Dynamics AX to a client application. For example, if you want to return information about a table such as what indexes exist on that table, you can use the metadata service.

System Service: User Session Service: - Use to retrieve information about the user session.

Enables you to return information about the current Windows user. You can return information such as the user’s default language, Default Company, default company time zone, permissions to access-controlled items, and so on



Adapter:

HTTP adapter – This adapter provides for synchronous message exchanges by using an HTTP or HTTPs transport.

NetTCP adapter – This adapter provides for synchronous exchanges by using WS-* standards support over the Transmission Control Protocol (TCP) transport. This adapter corresponds to the WCF-NetTcp binding in Windows Communication Foundation (WCF).

MSMQ adapter – This adapter provides support for queuing by using Message Queuing as a transport. Message Queuing is also known as MSMQ. Message Queuing is a type of asynchronous communication. This adapter corresponds to the WCF-NetMsmq binding in WCF.

File system adapter – This adapter provides support for the asynchronous exchange of documents through file system directories.

Windows Azure Service Bus adapter – This adapter enables publishing AX 2012 services by using the Windows Azure Service Bus. The Service Bus provides the messaging channel for connecting your cloud applications to your on-premises applications, services and systems.

This adapter requires Internet Information Services (IIS) 7.5, authentication for inbound Service Bus messages, and registration of a Service Bus namespace. Cumulative update 6 or later for AX 2012 provides classes to

support the required authentication in addition to the infrastructure to register a Service Bus namespace from AX 2012.

http://axwonders.blogspot.com/2012/01/microsoft-dynamics-ax-2012-services-and.html

https://community.dynamics.com/ax/b/axwonders/archive/2012/01/24/microsoft-dynamics-ax-2012-services-and-application-integration-framework-aif-architecture

http://ax2012aifintegration.blogspot.in/2015/06/microsoft-dynamics-ax-2012-class.html

https://social.technet.microsoft.com/wiki/contents/articles/33257.biztalk-server-lob-integration-dynamics-ax.aspx

1. AIFGatewayReceiveService – this service communicates with the adapters, receives messages from their external source locations, and puts them into the gateway queue to wait for processing.
2. AIFInboundProcessingService – this service takes incoming messages from the gateway queue and then processes the documents according to the rules that are specified by the inbound port.
3. AIFOutboundProcessingService – this service processes an outbound document according to the rules that are specified by the integration port and then adds the envelope XML code to create a fully-formed AIF message. The service then places the message into
the gateway queue to send.
4. AIFGatewaySendService – this service sends the messages to the correct external destinations.


How documents are exchanged
AIF provides an extensible framework for the exchange of XML documents with external systems. The framework supports both synchronous andasynchronous transports.
In synchronous mode, requests are tightly coupled to responses, which means that the submitter of the request must wait for a response from AIF before proceeding.  In this case, AIF does process the request immediately and then sends a response.

In asynchronous mode, however, requests are placed into a queue, called thegateway queue. Queued messages are processed at a later time and AIF sends a response when processing is completed. In this case, responses are delayed, but note that large volumes of messages can be processed more efficiently, and message processing can be controlled by changing various configuration settings.




  1. Service operation

    Service operations are class methods that expose any business logic in a service. To define a service operation, add the SysEntryPointAttribute attribute at the top of a method. Any existing method can be converted to a service operation by adding this attribute at the beginning of the method. 
    &absp;
    Note:
     The service operation name cannot include Create, Find, Update or Delete. These names are reserved to be used by AIF Document services. AX will make an exception when they are called from a client.
  2. SysEntryPointAttribute

    SysEntryPointAttribute defines the authorization checks that will be performed when a method is called from the server. This attribute must be set on all the service operations. If the value is “true”, it means that authorization checks will be performed for all the tables accessed in the method and if set to “false”, no authorization checks will be performed.
  3. AifCollectionTypeAttribute

    AifCollectionTypeAttribute is used when you want to use a collection as a return type or in a parameter of a service operation. This attribute defines the type of data a collection contains.



Friday 20 March 2015

Enterprise portal common methods in ax


Below code will help to get the value of the field from enterprise portal

we can retrive the value from Grid / group / form using below code

DataSetViewRow row = CurrentRow;
string accountnum= string.Empty;

        if (row != null)
        {
            accountnum= (string)row.GetFieldValue("custTrans!AcountNum");
        }
____________________________________________________________________________


Solution:
1. Open the web control in Visual studio
2. Open the Design file of the web control (.ascx)
3. Click source button to view Ascx coding (HTML code)
4. Find(ctrl + F ) Metadata in the ascx code
5. Simply delete the word whereever it is appear in ascx file
6. Save and deploy the webcontrol.
7. Open the webpage again, the error is resolved.

private DataSetViewRow CurrentExpenseHeaderRow
    {
        get
        {
            DataSetView dsv = this.DS_TrvExpTable.GetDataSet().DataSetViews["TrvExpTable"];
            return (dsv == null) ? null : dsv.GetCurrent();
        }
    }

    private IAxaptaRecordAdapter CurrentRecord
    {
        get
        {
            return (this.CurrentRow == null) ? null : this.CurrentRow.GetRecord();
        }
    }

    private IAxaptaRecordAdapter CurrentExpenseHeaderRecord
    {
        get
        {
            return (this.CurrentExpenseHeaderRow == null) ? null : this.CurrentExpenseHeaderRow.GetRecord();
        }
    }
_________________________________________

Call dynamics AX dataset method in Enterprise portal

 

boolean isValid = ((bool)this.DS_TSTimesheetEntry.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call("validateTSTimesheetLineWrite"))
________________________________________________________________________________

How to use infolog in Enterprise portal


Proxy.Info obj = new Proxy.Info(this.AxSession.AxaptaAdapter);
obj.add(Proxy.Exception.Info, "Testing");
________________________________________________________________________________

How to call method other Webcontrol method in Enterprise portal


TrvUtility.GetAdminCustomFieldsDictionary(this.AxSession, this.Page.Session, TrvUtility.AdminCustomFields.Transaction);
________________________________________________________________________________

How to refer / add exisitng webcontrol in your web control

Needs to write the below code in design form
<%@ Register Src="TrvUtility.ascx" TagName="AxUtility" TagPrefix="AxUtil" %>
________________________________________________________________________________


How to access enum values in Enterprise portal

ApplicationProxy.TrvAppStatus approvalStatus;

approvalStatus = ((ApplicationProxy.TrvAppStatus)this.CurrentExpenseHeaderRow["ApprovalStatus"]);

approvalStatus = ApplicationProxy.TrvAppStatus.None;

return (ApplicationProxy.TrvAppStatus)approvalStatus;
________________________________________________________________________________

compare Enum values

if ((ApplicationProxy.TrvExpType)this.CurrentRow["ExpType"] == ApplicationProxy.TrvExpType.Hotel)
                {
                    long recId = this.CurrentRow == null ? 0 : System.Convert.ToInt64(this.CurrentRow["RecId"], CultureInfo.InvariantCulture);
                    guestsLabel = ApplicationProxy.EPTrv.getGuestLabel(recId);
                }
 ____________________________________________________________________________

How to enable\ disable fields in Grid

foreach (DataControlField dcf in this.AxGroup_ExpenseHeaderOverviewLeft.DataControlFieldCollection)
            {
                axbf = dcf as AxBoundField;
                if (axbf != null)
                {
                    switch (axbf.DataField)
                    {
                        case "ExpNumber":
                        case "employeeName**":
                        case "Txt1":
                            axbf.Visible = true;
                            break;
                    }
                }
            }

How to enable\ disable fields in Group
            foreach (DataControlField dcf in this.AxGroup_ExpenseHeaderOverviewRight.DataControlFieldCollection)
            {
                axbf = dcf as AxBoundField;
                if (axbf != null)
                {
                    switch (axbf.DataField)
                    {
                        case "TrvRequisition!RequisitionNumber":
                        case "totalAmountAuthorized**":
                        case "totalApprovalAmountWithCurrencyCode**":
                            axbf.Visible = true;
                            break;

                        // Description is shown on right group during create, and on left group for Approver, for UX reasons
                        case "Txt1":
                            axbf.Visible = false;
                            break;
                    }
                }
            } 
__________________________________________________________________________________


 bool custVendGroupHideForApprover = true;
if (this.AxGroup_ExpenseHeaderCustomerVendorForApprover.Visible)
        {
            foreach (DataControlField dcf in this.AxGroup_ExpenseHeaderCustomerVendorForApprover.DataControlFieldCollection)
            {
                if (dcf is AxBoundField)
                {
                    // If any field is visible, do not hide the group
                    if (((AxBoundField)dcf).Metadata.Visible)
                    {
                        custVendGroupHideForApprover = false;
                        break;
                    }
                }
            }

            this.AxGroup_ExpenseHeaderCustomerVendorForApprover.Visible = !custVendGroupHideForApprover;
        }
________________________________________________________________________________
get particular table field value in visual studio
<dynamics:AxGroup ID="AxFieldGroupDefaultsProject" runat="server"
                    Caption="<%$ AxLabel:@SYS4534 %>">
                <Fields>
                    <dynamics:AxBoundField DataSet="TrvExpTableNew"DataSetView="TrvExpTable"
                        DataField="ProjId" SortExpression="ProjId" AutoPostBack="true" OnDataChanged="ProjId_OnDataChanged"/>
                </Fields>
            </dynamics:AxGroup>
While adding the bound fields to the AxForm, we won’t get this attributeAutoPostBack="true" to the AxBoundField.
To raise the OnDataChanged event,  explicitly need to add the above attribute toAxBoundField.
Then I had added the following code to the event …
protected void ProjId_OnDataChanged(object sender,AxBoundFieldDataChangedEventArgs e)
    {
        string expProjId = ((System.Web.UI.WebControls.TextBox)(e.BoundControl)).Text.ToString();

                if (expProjId != "")
                {
                    ButtonOK.Enabled = true;
                }
                else
                {
                    ButtonOK.Enabled = false;
                }          
    }
________________________________________________________________________________


string  var = (string)this.EpDataSourceName.GetDataSet().DataSetViews["DataSourceName"].GetCurrent().GetFieldValue("Fieldname");

Example:
I have get vendor account value from PurchReqCreateDataset
string  vendorID = (string)this.PurchReqCreateDs.GetDataSet.DataSetViews["PurchReqTable"].GetCurrent().GetFieldValue("VendAccount");

_______________________________________________________________________________

Upload document through EP
To provide document attachement feature on EP form to upload documents, need to follow below setps 
1-Add new datasource by using EPDocuInfoAdd data set from AX
2-Add new ASP:FileUpload control on page
3-On Ok/Submit button call below method after Inserting/Updating record

private void DocumentUpload()
{
DataSetView datasetViewAppl = DataSourceName.GetDataSourceView(AXFormControlName.DataMember).DataSetView;

DataSetViewRow docuRefAdd = this.dsDocuRef.GetDataSourceView("DocuRef").DataSetView.AddNew();
DataSetViewRow docuRefCurrent = this.dsDocuRef.GetDataSourceView("DocuRef").DataSetView.GetCurrent();

IAxaptaRecordAdapter docuRefRecord = docuRefCurrent.GetRecord();
docuRefRecord.SetField("RefTableId", (object)datasetViewAppl.GetCurrent().GetFieldValue("TableId"));
docuRefRecord.SetField("RefRecId", (object)datasetViewAppl.GetCurrent().GetFieldValue("RecId"));
docuRefRecord.SetField("TypeId", "File");

string[] myFiles = Request.Files.AllKeys;
bool dataSaved = false;
if (FileUpload1.HasFile)
{
using (IAxaptaRecordAdapter irecDocuValue = ApplicationProxy.EPDocumentHandling.saveWebDocumentClient(
AxSession.AxaptaAdapter,
docuRefRecord,
Request.Files.AllKeys[0]))
{
{
if (irecDocuValue != null)
{
// Get the RecId of the insert DocuValue record.
Int64 valueRecId = (Int64)irecDocuValue.GetField("RecId");

if (valueRecId != 0)
{
//Update the ValueRecId field of the DocuRef record with the RecId of the DocuValue record
docuRefRecord.SetField("ValueRecId", (object)valueRecId);

// Saves the DocuRef record in the DB.
ApplicationProxy.EP.createDocuRef(AxSession.AxaptaAdapter, docuRefRecord);

// Set this parameter to enable redirection.
dataSaved = true;
}
else
throw new System.Exception("File upload error");
}
}
}
}