Showing posts with label AX2012. Show all posts
Showing posts with label AX2012. Show all posts

Tuesday, 25 October 2016

How to create and test the DLL of AX2012 service

This post will demonstrate the creation of  DLL with AX2012 service and than testing the DLL from Visula studio.

Hi guys this requirement is not very common and I could hardly found any post which share the details about this. I did a POC for a requirement where the third party software was not enough capable to directly consume the AX2012 SVC.

In order to provide a solution we created DLL out of the AX2012  service and than tested the same DLL using as a reference in visual studio.

Step: 1 Create DLL for your existing service.
Goto Visual Studio --> New --> Project --> C# --> ClassLibrary --> Add service reference
  
Step 2: Set your project to release mode.


Step 3: Build the project and copy the dll from release folder.
Release folder path
Step 4: Go to config in same VS project and copy the endpoint address and save it for later use.
Now close the VS solution. Your DLL is ready to be used copy this dll to any other location on your system.

Step 5: To test the same dll we need to create another VS solution.
Goto --> File --> New --> Projects --VisualC# --> ConsoleApplication.
Step 6: Add reference to you dll.
Goto --> Solution Explorer --> Reference --> Right click --> Add new reference
Step 7: Browse to the dll folder path and select dll file to be added.
Step 8: Repeat step 6 and add one more service reference from Assembly.

Step 9: Add below code to your console application
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StudentTableDll.StudentService;
using System.Configuration;
using System.ServiceModel;
namespace TestDLLDemo
{
class Program
{
static void Main(string[] args)
{
EndpointAddress ep = null;
System.ServiceModel.NetTcpBinding tcpb = new System.ServiceModel.NetTcpBinding();
System.ServiceModel.ChannelFactory channelFactory = new System.ServiceModel.ChannelFactory<StudentTableService>(tcpb);

// End Point Address taken from step 4 in same blog

string strEPAdr = "net.tcp://ax2012r3dev:8201/DynamicsAx/Services/StudentTable";
ep = new EndpointAddress(strEPAdr);
StudentTableServiceClient client = new StudentTableServiceClient(tcpb, ep);
AxdStudentTable axd = new AxdStudentTable();
CallContext context = new CallContext();
context.Company = "EAM";
context.Language = "en-au";
AxdEntity_StudentTable studentTable = new AxdEntity_StudentTable();
studentTable.Name = "Kumar";
studentTable.Standard = "Eight";
studentTable.RollNumber = 01;
axd.StudentTable = new AxdEntity_StudentTable[1] { studentTable };
try
{
EntityKey[] returnFloc = client.create(context, axd);
EntityKey returnedFloc = (EntityKey)returnFloc.GetValue(0);
Console.WriteLine("the record has been created RECID- " + returnedFloc.KeyData[0].Value);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.ReadLine();
}
}
}
}

Step 9: Before running the code please ensure the below highlighted points.


Step 10: Run to code to create the record in student table.

Happy daxing :)

Monday, 24 October 2016

AIF AX 2012  Document service operations

Basically we deal with normal service (CRUD) operation while creating a document service. I hope everyone who came to this post might be aware of basic CRUD operations. Hence, I will explain them in brief whereas will try to focus on other operations available in AX 2012 document service and will be more useful.

Create: Create operation will insert the record as per the document service query. It performs create operation on all the related data sources  which are related in query if specified.

Read: Read operation read the document based on passed entity key and return the AXd class instance which contains information about all the related datasets.

Update: There is often requirement to update the record from third party applications, hrnce need to use update operation in such scenarios.

Delete: Delete operation has been rarely used but, is called when we need to delete the record when instructed by third party application.

Find: Find operation works similar as it is in X++, it will try to find the record based on criteria specified for find operation and return the record.

findKeys: This operation is similar to find operation where as it is different in terms of return value, it return only the entity keys required, whereas find returns the complete record. This operation is used when the service is deployed using enhanced port only.




Code to trigger outbound service AX AF 2012

We often get the requirement to export the the xml file for a particular document using outbound port. Outbound port can be triggered normally through AIF gateway classes in batch. Further their are requirements where we may need to generate the XML  using outbound port on any particular event.

Below is the code which can be placed on any event handler to trigger a outbound port configured for the XML document.

Sample X ++ code:

public client server static void OutboundFileSytemAdapterInvokeJob(XppPrePostArgs _args)
{
  SalesTable              salesTable;
  AxdSendContext          axdSendContext = AxdSendContext::construct();
  Map                     keyData;
  ClassId                 serviceClass;
  AifConstraint           aifConstraint = new AifConstraint();
  AifConstraintList       aifConstraintList = new AifConstraintList();
  AifActionId             actionId;
  AifEndpointList         endpointList;
 
  AIFGatewaySendService   aIFGatewaySendService = new AIFGatewaySendService();
  AifEntityKey            aifEntityKey  = AifEntityKey::construct();
  #define.xmlServiceRead('SalesSalesOrderService.read')
 
 
     
  salesTable= _args.getThis();
 
  if(salesTable.RecId)
  {
   keyData = SysDictTable::getKeyData(salesTable);
   aifEntityKey.parmTableId(salesTable.TableId);
   aifEntityKey.parmRecId(salesTable.RecId);
   aifEntityKey.parmKeyDataMap(keyData);
   axdSendContext.parmXMLDocPurpose(XMLDocPurpose::Original);
   axdSendContext.parmSecurity(false);
   serviceClass = className2Id(classStr(SalesSalesOrderService));
   aifConstraint.parmType(AifConstraintType::NoConstraint);
   aifConstraintList.addConstraint(aifConstraint);
   if(serviceClass)
   {
    //Get the actionId of the default action for this document class
    actionId = AifSendService::getDefaultSendAction(serviceClass, AifSendActionType::SendByKey);
    actionId =  xmlServiceRead;
 
    if(actionId)
    {
     //Get the list of valid Endpoints
     endpointList = AifSendService::getEligibleEndpoints(actionId, aifConstraintList);
     AifSendService::submit(actionId,endpointList,aifEntityKey,AifSendMode::Sync,axdSendContext.pack(),AifProcessingMode::Parallel);
    }
   }
   AIFGatewaySendService.run();}
 }
}

Sunday, 23 October 2016

C# code to update the Logistics postal address through AIF.

In my second post of this series, I demonstrated the creation of document service for a new entity. The post also include the solution on how to add the related postal address using AIF document service.

In order to achieve this we have added  calls to some standard API's in prepareForSaveDetailsExtended() method of our service class.

In this post I am sharing the code which can be used to test the update operation on student entity with address.

In order to update the surrogate key indexed entity, we need to use the find operation for finding the entity key, and then based on the found entity key we can do the read operation which will return the Axd class instance which can be updated as per the requirement. Below is the code which will demonstrate the same requirement.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestStudentService.ServiceReference1;//Added namespace o access service in below application

namespace TestStudentService
{
class Program
{
static void Main(string[] args)
{
int rollNumber = 4;

AxdStudentTable studentAxd = null;
CallContext context = new
CallContext();
context.Company = "EAM";

StudentTableServiceClient proxy = new StudentTableServiceClient();
try
{
studentAxd = proxy.read(context, Program.readCritera(rollNumber));
//Console.WriteLine("Read worked");
Program.updateCustomer(studentAxd, rollNumber);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
private static EntityKey[] readCritera(int rollNumber)
{
StudentTableServiceClient client = new StudentTableServiceClient();
AxdStudentTable localAxd = new AxdStudentTable();

CriteriaElement[] criteriaElements = new CriteriaElement[1];
criteriaElements[0] = new CriteriaElement();
criteriaElements[0].DataSourceName = "StudentTable";
criteriaElements[0].FieldName = "RollNumber";
criteriaElements[0].Value1 = rollNumber.ToString();
QueryCriteria queryCriteria = new QueryCriteria();
queryCriteria.CriteriaElement = criteriaElements;
CallContext readContext = new
CallContext();
readContext.Company = "EAM";
//Using find operation
localAxd = client.find(readContext, queryCriteria);
//Using read operation
EntityKey[] entityKeyList = new EntityKey[1];
EntityKey key = new EntityKey();
KeyField[] keyFields = new KeyField[1];
KeyField keyField = new KeyField();
keyField.Field = "RecID";


keyField.Value = localAxd.StudentTable[0].RecId.ToString();
keyFields[0] = keyField;
key.KeyData = keyFields;
entityKeyList[0] = key;
return entityKeyList;
}
private static void updateCustomer(AxdStudentTable studentTableAxd, int rollNumber)
{
try
{
StudentTableServiceClient updateProxy = new StudentTableServiceClient();
CallContext updateContext = new CallContext();
updateContext.Company = "EAM";

AxdEntity_StudentTable OldStudentEntity = studentTableAxd.StudentTable[0];
AxdEntity_StudentTable newStudentEntity = new AxdEntity_StudentTable();
AxdStudentTable newStudentAxd = new AxdStudentTable();

newStudentAxd.ValidTimeStateType = studentTableAxd.ValidTimeStateType;
newStudentAxd.ValidTimeStateTypeSpecified = true;

newStudentAxd.ValidAsOfDateTime = studentTableAxd.ValidAsOfDateTime;
newStudentAxd.ValidFromDateTime = studentTableAxd.ValidFromDateTime;
newStudentAxd.ValidToDateTime = studentTableAxd.ValidToDateTime;
newStudentEntity._DocumentHash = OldStudentEntity._DocumentHash;
newStudentEntity.RecId = OldStudentEntity.RecId;
newStudentEntity.RecVersion = OldStudentEntity.RecVersion;
newStudentEntity.action = AxdEnum_AxdEntityAction.update;
newStudentEntity.actionSpecified = true;
newStudentEntity.Name = "Suresk kumar";
#region Update the date effective entities
newStudentEntity.DirPartyTable = OldStudentEntity.DirPartyTable;
newStudentEntity.DirPartyTable[0].action = AxdEnum_AxdEntityAction.update;
newStudentEntity.DirPartyTable[0].actionSpecified = true;
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].StreetNumber = "10";
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].Roles = "Home";
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].Street = "street updated 1223";
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].action = AxdEnum_AxdEntityAction.update;
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].actionSpecified = true;
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].updateMode = AxdEnum_ValidTimeStateUpdate.Correction;
newStudentEntity.DirPartyTable[0].DirPartyPostalAddressView[0].updateModeSpecified = true;
newStudentEntity.DirPartyTable[0].DirPartyContactInfoView[0].Locator = "+61 (0) 12 345 678";
newStudentEntity.DirPartyTable[0].DirPartyContactInfoView[0].Roles = "Home";
newStudentEntity.DirPartyTable[0].DirPartyContactInfoView[0].Type = AxdEnum_LogisticsElectronicAddressMethodType.Phone;
newStudentEntity.DirPartyTable[0].DirPartyContactInfoView[0].action = AxdEnum_AxdEntityAction.update;
newStudentEntity.DirPartyTable[0].DirPartyContactInfoView[0].actionSpecified = true;

newStudentAxd.StudentTable = new AxdEntity_StudentTable[1] { newStudentEntity };
#endregion
updateProxy.update(updateContext, Program.readCritera(rollNumber), newStudentAxd);
Console.Write("Worked");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Failed");
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}



In my next post I will demonstrate the use of methods of document service class which we can use for our customizations.