Wednesday, June 15, 2016

Using XE Currency Restful API in AX - Using Basic Authentication method



static void XECurrencyConverionRestfulAPI(Args _args)
{
    System.Net.HttpWebRequest           webReq;
    System.Net.HttpWebResponse          webRes;
    CLRObject                           clrObj;
    System.IO.Stream                    stream;
    System.IO.StreamReader              streamRead;
    System.IO.StreamWriter              streamWrite;
    System.Net.ServicePoint             servicePt;
    System.Net.WebHeaderCollection      headers = new System.Net.WebHeaderCollection();
    str                                 userNamePassword, userNamePassword64, ret;
    System.Byte[]                       byte;
    System.Text.Encoding                encoding = System.Text.Encoding::get_UTF8();
 
    //This line gives the user control to run unmanaged and managed code
    new InteropPermission(InteropKind::ClrInterop).assert();
    // Create Object for adding headers
    headers = new System.Net.WebHeaderCollection();
    clrObj = System.Net.WebRequest::Create('https://xecdapi.xe.com/v1/currencies.xml');
    webReq = clrObj;
    //Set Method Type
    webReq.set_Method("GET");
    webReq.set_KeepAlive(true);
    // Set Content type
    webReq.set_ContentType("application/xml");
 
    try
    {
        userNamePassword = 'YOURUSERNAME:YOURPASSWORD';
        //64 bit encode user name and password
        byte = encoding.GetBytes(userNamePassword);
        userNamePassword64 = System.Convert::ToBase64String(byte);
        headers.Add("Authorization", 'Basic ' + userNamePassword64);
 
        //Add header to request
        webReq.set_Headers(headers);
        //Gets the response object
        webRes = webReq.GetResponse();
    }
    catch (Exception::CLRError)
    {
        //Access the last CLR Exception
        info(CLRInterop::getLastException().ToString());
     
        //See AifUtil::getClrErrorMessage for another alternative
        //how to parse the Exception object
    }
    //Get Stream
    stream = webRes.GetResponseStream();
    streamRead = new System.IO.StreamReader(stream);
    ret = streamRead.ReadToEnd();
    stream.Close();
    webRes.Close();
}

Tuesday, March 15, 2016

Unable to cast object of type 'Dynamics.Ax.Application.DictField' to type 'Dynamics.Ax.Application.SysDictField

I found some standard Microsoft code in AX which was working fine in x++ however, when the code executed in IL (Aif Interface), it would throw an error

"Unable to cast object of type 'Dynamics.Ax.Application.DictField' to type 'Dynamics.Ax.Application.SysDictField"

I found that the variable was declared as SysDictField but the object was instantiated as new DictField() - this works fine in x++ but would fail in IL based on OOP principles. 

The solution was to change the following line of code from new dictField(...) to new sysDictField(...)

SysDictField        dictField;

dictField   = new dictField(_variable.RefTableId,_variable.RefFieldId);

should be:

dictField   = new SysDictField(_variable.RefTableId,_variable.RefFieldId);

Wednesday, December 16, 2015

No matching MessageFilter was found for the given Message

We are calling an AIF web service from a .Net API. Everything was working and suddenly after a model store deployment, we were unable to use that service and were getting following error.

No matching MessageFilter was found for the given Message

I tried everything and could not find anything wrong. Web.config, WCF bindings everything was OK but still it would not work.

After spending couple of hours, I removed the Service References (not just update, remoed and re-added) from my code, rebuilt the API and published on IIS again and it started working.

Sunday, December 6, 2015

Sales order confirmation in batch - adding extended logic

The out of the box Sales order confirmation functionality allows us to either confirm Sales order using a click of a button (on Sales order form/list page) or we can schedule the confirmation of Sales order using a batch job (it also supports late selection query). This all works fine. However, if you want to perform additional tasks on each Sales order once it is confirmed, you will need to write some code. The class structure is something like that

FormLetterService
SalesFormLetter
SalesFormLetter_Confirmation

Any developer familiar to inheritance would go and override the run method of SalesFormLetter_Confirmation class to perform the additional updates after the super call and it will work perfect when a Sales order is confirmed using a button. However, it will NOT work as expected when runs under a batch. It is because, batch creates multi threaded tasks and leaves them to execute later. The code written in run method of SalesFormLetter_Confirmation class would run before the Sales order is actually confirmed (under different thread) and you will not achieve your desired results as code would not be execute for SOs being confirmed under a batch.

To overcome this issue, the code must be executed when the thread actually confirms the Sales order. After performing some debugging using Visual Studio and analysing the threads I found few ways to achieve the desired results and execute the custom code for each and every Sales order under the batch right after it gets Confirmed.


  1. There is a class called "FormLetterServiceBatchTaskManager". It has run method - write your code there after the base class' run gets executed. Better check the this.ParmDocumentStatus to execute your code only for the document type you are working on. (if this.ParmDocumentStatus() == DocumentStatus::Confirmation)
  2. Write your code in FormLetterService.run() method after journal gets created (Again, check the document status and execute your code only for your desired document type). 
There are some other classes which actually creates journal and they could also be considered for performing similar tasks based on your requirements.
  1. FormLetterJournalCreate (Parent class - following are few of its child classes)
  2. SalesConfirmJournalCreate
  3. SalesPickingListJournalCreate etc.

Dynamics AX Load Balancing tips

Working with Single AOS environment and Load balanced environment is very different. Specially, when it comes to releasing code in production environment or making changes in AIF service data policies. Following are few things which I learnt in my recent project:


  1. If running multiple AOSs for load balancing and you need to make data policy changes (i-e need to enable or disable fields in a web service), you must bring all AOSs down and restart the service when change is made and CIL is performed.
  2. If running multiple AOSs and made some code change that needs CIL change. Again, must bring all AOSs down and restart them when change is made to make the change effective in all environments (servers)
  3. If running multiple AOSs and modified workflow (i-e a new workflow version is added), Must refresh cache in all other environments. You don't need to bring production environment down for that purpose and just login to all servers and refresh the cache (Tools > Cache > Refresh AOD, data, dictionary)
  4. If you are using load balancing and you have written custom .net API which calls AIF services. The custom .Net API MUST be deployed on physical cluster and not the load balanced one. Otherwise, it won't be able to authenticate and you will get NTLM authentication error.

I will keep updating this post as I find and learn more. 

Tuesday, October 27, 2015

Start Visual Studio in CUS, VAR layer

If you are developing for EP and creating/modifying web controls. You would notice that changes you make in Visual Studio will be published in USR layer. To start visual studio in some other layer, create a Visual Studio shortcut > Right Click > Properties and set target to something like this:

"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe" /AxConfig  "C:\AXCU8_DEV10_VAR.axc"

The highlighted text is basically pointing to the AX configuration file for VAR, CUS layer.

Saturday, August 15, 2015

AX 7 - New Features

Recently, I came across a white paper providing summary of new features that have been implemented in AX7.  The paper needed partner source access so I am providing highlights here for those who don't have access to partner source. Please note that the White paper is draft and subject to change.

AX  NEW FEATURES:
FOUNDATION
What can you do?
AX 2012
‘AX 7’
Access the client, anytime, anywhere
The AX 2012 desktop client provided a full set of forms, but was limited to running on Windows machines and required installation. Terminal Server was often used with the desktop client to enable access over a WAN. The Enterprise Portal web client provided a reduced set of forms.
The two AX 2012 clients have been replaced by a single, standards based web client that provides the full set of functionality of the desktop client with the reach of the Enterprise Portal client.



FINANCIALS MANAGEMENT
What can you do?
AX 2012
‘AX 7’
Export account structures to Excel

Not supported
You can now select an account structure and export that to Excel.
View ledgers and advanced rule structures associated with an account structure on a single form
In AX 2012, the user has to navigate to multiple forms to see the ledger that the account structure is using.
Fact boxes have been added to the account structure form.
Filter Management Reporter (labeled Financial reporting in ‘AX 7’) reports based on dimension, attributes, dates, and scenarios
All filtering of Management Reporter reports was handled through the design of the report. If a user with viewing privileges wanted to view a report for a different date, for example, this required a report designer to make the modification
Report options have been added so when viewing a report, different filters can be applied and a new report is generated based on those filters.
View Management Reporter (financial reports) within the ‘AX 7’ client
A separate web client was used for viewing Management Reporter reports.
A list of all financial reports can be accessed within the ‘AX 7’ client. The user selects a report to view, and the report is rendered within the ‘AX 7’ client.
Monitor budget vs actuals and create ledger forecasts using the Ledger budgets and forecasts workspace and additional inquiry forms
Not available
The workspace can be accessed through the ‘AX 7’ dashboard. It includes links to a number of new inquiry forms: Actuals vs budget summary, Budget control statistic summary, Budget register entries, Budget plans.
Create layouts for budget plans and forecasts
The Budget plan document is viewed as a list of lines with effective dates and amounts for financial dimension combinations. The user must create and use Excel templates to view budget plan data in a pivot.
An unlimited number of layouts is available for budget plans and forecasts. You can combine selected financial dimensions, user defined columns, and other row attributes (such as comments, projects, assets, etc.) in the layout. Users can switch the layout for the budget plan document on the fly and edit data using any selected layout. Budget planning configuration is simplified by eliminating scenario constraints and using layouts to define which data can be viewed and edited in each budget plan document stage.
Print the Vendor Invoice Transactions report with information from the Detailed Due Day List which includes the days past due.
In AX 2012, you had to print two different reports: the “Detailed Due Day List” and the “Vendor Invoice Transactions” report.
The information contained on the two reports were consolidated onto the “Vendor Invoice Transactions” report. The Detailed Due Day List was deprecated.


HUMAN CAPITAL MANAGEMENT
What can you do?
AX 2012
‘AX 7’
Transfer skills and certificates to class participants upon course completion
Manual process in AX 2012.
Upon completion of a course a new option will be available to update participant’s records with the new skills and certificates.
Quick employment verification capability
Manual process in AX 2012
Accessed from a workspace or the employee form HR can quickly verify employment.
Enable employees to view, update, and delete information from the system
Available in AX 2012 with limited view and update capability.
This feature is enabled for employees and contractors to view a wide range of personal data with optional workflow when creating new, updating existing, or deleting information from the system.
Enable managers to view or edit employee information
Available in AX 2012 with limited view and update capability.
Managers are empowered based on configuration settings and security to view or edit employee information.
Encrypt ID numbers
Not Available
All Employee ID (SSN) numbers are encrypted.
Access compensation processing results
Available only at time of processing
Compensation processing results can now be accessed at any point after the process has run.
Access benefit processing results
Available only at time of processing
Benefits processing results can now be accessed at any point after the process has run.
View Date Effective timeline changes
Not Available
This comparison tool is available for Employees, Positions, and Jobs. It provides a comprehensive view of changes from one version of a record to another.
View employees by company
Manual process in AX 2012 through filtering
Employee and Contractor lists are automatically filtered by the company you’re logged into.
Update course participants list
Not Available
Course participants can be removed from the participants list.
Manage compensation events in mass
Not Available
This feature provides a streamlined processing of compensation changes for employees.


Wednesday, August 12, 2015

AX 2012 Get Item purchase price using x++

Question: I need to get Item purchasing price using x++ code.

Answer:

container result;

result = PriceDisc::findItemPriceAgreement(ModuleInventPurchSales::Purch, ItemId, InventDim, Unit, today(), Qty, VendAccountNum, CurrencyCode, "0");

purchPrice            = conPeek(result, 0);

Note: The variables shown above to pass as parameters are self explanatory and should be replaced with your variables.

Monday, August 10, 2015

Redirect page to some other page when dialog closed on EP

Recently, we had a requirement to open a dialog page from list page and when user closes the dialog, we had to redirect our page to some other page. I know it can be done very easily by handling the close dialog event handler. However, we are talking about list page here. Where we don't have option to write c# code. This is where the web development skills comes into play and can help you achieve some fast results where you don't have much time to modify sharepoint web parts etc.

I was able to accomplish this using Javascript. I registered the closeWindow handler when the dialog was loaded, built the URL for the EP menu item using c# code and registered the script. Whenever the dialog would close, a javascript function would execute to redirect the page. Remember, in my case, the requirement was to redirect the page but if you have some other requirement when closing the dialog, you can achieve that as well. Sample code:

protected void Page_Load(object sender, EventArgs e)
    {
        String linkOneURL;
        String clientScriptName = "CloseWindow";
        Type clientScriptType = this.GetType();
        ClientScriptManager cs = Page.ClientScript;
        System.Text.StringBuilder javaScript = new System.Text.StringBuilder();
        AxUrlMenuItem shoppingCartPageMenuItem = new AxUrlMenuItem("EPCSSSalesBasket");
        String shoppingCartUrl = shoppingCartPageMenuItem.Url.OriginalString;
        String buildUrl = String.Empty;

        if (!IsPostBack)
        {
        
            linkOneURL = this.dsCustTable.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call("BuildLinkOneURL").ToString();
            this.LinkOneFrame.Attributes.Add("src", linkOneURL); // I am loading some third party page here under IFrame.

            if (!cs.IsStartupScriptRegistered(clientScriptType, clientScriptName))
            {
                buildUrl = "window.frameElement.navigateParent('" + shoppingCartUrl + "');"; // This is the URL i want to redirect.


                javaScript.Append("<script type='text/javascript'>");
                javaScript.Append("function UnLoadWindow() {");
                javaScript.Append(buildUrl);
                javaScript.Append("}");
                javaScript.Append("window.onbeforeunload = UnLoadWindow;");
                javaScript.Append("</script>");

                cs.RegisterStartupScript(clientScriptType, clientScriptName, javaScript.ToString()); // Registering the Javascript function - this would be executed when the dialog is closed.

            }
           
        }
    }

AX 2012 showing third party website in EP/Sharepoint dialog

We recently had a requirement to show a third party website in our EP site. The requirement was to show the website in Enterprise Portal dialog and URL was not static. We had to build URL at runtime by using fields from the selected record. As you know, we cannot write code on EP list page (we can use interaction class but we cannot write c# code for list page), so options were very limited. We added a Menu item button on List page and passed the selected record as context to that button. The button was pointing to a new web control (or sharepoint page) and we kept this page blank. All it had was an IFrame. See sample HTML below.

<dynamics:AxDataSource ID="dsCustTable" runat="server" DataSetName="dsCustTable" ProviderView="CustTable"></dynamics:AxDataSource>
<div style="height: 100%">  
    <iframe id="LinkOneFrame" runat="server" height="800" width="100%" ></iframe>
</div>

Now, we need to load our page in that IFrame. First thing was to get the URL as it is not a static URL but we need to build that on fly. We created a static method on table to build that using x++ and returned the URL from x++.

Following is the c# code to get the URL and load the page in URL.

linkOneURL = this.dsCustTable.GetDataSet().DataSetRun.AxaptaObjectAdapter.Call("BuildLinkOneURL").ToString();

this.LinkOneFrame.Attributes.Add("src", linkOneURL);

When you click the button on list page a new popup dialog would open and it would show the page in Iframe.

Sunday, May 10, 2015

AX2012 AIF Document Services - Include fields which are not part of AOT query

While exporting data from AX to other third party systems. There could be a requirement to send data which is not part of your AOT query. There could be a requirement to include data from other tables which are not part of your query OR cannot become part of query because of complex joins or may be they need some custom business logic which cannot be achieved using Query. You can always include such fields by creating parm methods for these fields in AX<tableName> classes. For example:

public str parmWBS(str _wbs = '')
{
    GeneralJournalEntry     generalJournalEntry;
    ProjInvoiceJour         projInvoiceJour;

    if (this.parmText() == '300')
    {
        select generalJournalEntry
            where generalJournalEntry.RecId == GeneralJournalAccountEntry.GeneralJournalEntry
            && generalJournalEntry.JournalCategory == LedgerTransType::Project
        join projInvoiceJour
            where projInvoiceJour.LedgerVoucher == generalJournalEntry.SubledgerVoucher;

        if (projInvoiceJour)
        {
            _wbs = projInvoiceJour.ProjInvoiceProjId;
        }
    }

    return _wbs;
}

In above method, based on the existing parmText() field on Query, I am trying to fetch the Project Invoice Id from the table which is not part of the query.

Once, parm method is written, you will need to:


  1. Run the Update Document Service Wizar
  2. Open AIFService forms, filter the service you are working on and click Refresh
  3. Generate Incremental IL

AX 2012 upload file to FTP with batch processing support

One of a very common requirements for any ERP systems is to have FTP file upload support to upload files from AX to FTP server. We do have many libraries, tools available to do that. However, it is best to have native X++ code without referencing any DLLs to upload your files to FTP from AX. Following code shows the example of uploading files to FTP.

The code written below can be easily used to upload files, However, if you have to process this as a batch you need to consider that batch runs on server/CIL and for this you need to set permissions and also if that still doesn't work, you can change the method to static server.

private server static void sendToFTP()
{
    System.Object ftpo;
    System.Object ftpResponse;
    System.Net.FtpWebRequest request;
    System.IO.StreamReader reader;
    System.IO.Stream requestStream;
    System.Byte[] bytes;
    
    System.Text.Encoding utf8;
    System.Net.FtpWebResponse response;
    System.Object credential;
    HOSInventParameters hosInventParameters;

    int             fileCount;
    System.Array    files;
    int             i;
    str             nextFile;
    Filename        filepath;
    Filename        fileType,fileNameString;
    FileNameType    pattern = '*.TXT';
    FileName        ftpFileName,fileName;


    select firstOnly custInventParameters;
    new InteropPermission(InteropKind::ClrInterop).assert();



    files           = System.IO.Directory::GetFiles(custInventParameters.PartsFileLocation, pattern);

    if (files)
    {
        fileCount =    files.get_Length();

        for(i=0; i < fileCount; i++)
        {
            nextFile    = files.GetValue(i);

            [filepath, filename, fileType] = fileNameSplit(nextFile);
            fileNameString= filename + fileType;
            ftpFileName = custInventParameters.PartsFTPAddress + '/'custInventParameters.PartsFTPLocation + '/' + fileNameString;

            reader = new System.IO.StreamReader(nextFile);
            utf8 = System.Text.Encoding::get_UTF8();
            bytes = utf8.GetBytes( reader.ReadToEnd() );
            reader.Close();
            // little workaround to get around the casting in .NET
            ftpo = System.Net.WebRequest::Create(ftpFileName);
            request = ftpo;

            credential = new System.Net.NetworkCredential(custInventParameters.PartsUserId,custInventParameters.PartsFTPPassword);
            request.set_Credentials(credential);
            request.set_ContentLength(bytes.get_Length());
            request.set_Method('STOR');
            // "Bypass" a HTTP Proxy (FTP transfer through a proxy causes an exception)
            // request.set_Proxy( System.Net.GlobalProxySelection::GetEmptyWebProxy() );
            requestStream = request.GetRequestStream();
            requestStream.Write(bytes,0,bytes.get_Length());
            requestStream.Close();

            ftpResponse = request.GetResponse();
            response = ftpResponse;
            info(response.get_StatusDescription());
        }
    }

    CodeAccessPermission::revertAssert();
}


Monday, April 6, 2015

Calling RESTful services using AX 2009, AX 2012


While integrating Dynamics AX with other systems, you might need to call REST services in Dynamics AX to Pull data in AX or Push data out of AX to other systems. REST services are the easiest and very useful way to provide the interface between 2 systems. The Job written below is the example of how one can call REST service from within AX.

Tip: Either you want to push data from AX or pull data in AX, you can always use POST method. In case you want to send data out of AX, you will always need to use POST method with your data as shown below in postData variable. In case, you need to download data in AX from some other system, you can still use POST method and send your credentials, API key for authentication purpose and download your data either in XML or JSON format as I have done in returnValue variable in job written below.

static void Job1(Args _args)
{
    str                             url;
    str                             postData;
    str                             returnValue;
    System.Net.HttpWebRequest       request;
    System.Net.HttpWebResponse      response;
    System.Byte[]                   byteArray;
    System.IO.Stream                dataStream;
    System.IO.StreamReader          streamReader;
    System.Net.ServicePoint         servicePoint;
    System.Net.ServicePointManager  servicePointManager;
    CLRObject                       clrObj;
    System.Text.Encoding            utf8;

    ;

    postData = strfmt('api_key=%1&account_id=%2', "DEC8A896-9244-4FAB-ACB9-15B932E630CB", "3");

    new InteropPermission(InteropKind::ClrInterop).assert();

    url = "http://yoururl.com/services/api/external/authentication.ashx?login";

    clrObj = System.Net.WebRequest::Create(url);
    System.Net.ServicePointManager::set_Expect100Continue(false);

    request = clrObj;
    request.set_Method("POST");
    utf8 = System.Text.Encoding::get_UTF8();
    byteArray = utf8.GetBytes(postData);
    request.set_ContentType("application/x-www-form-urlencoded");
    request.set_ContentLength(byteArray.get_Length());

    dataStream = request.GetRequestStream();
    dataStream.Write(byteArray, 0, byteArray.get_Length());
    dataStream.Close();

    try
    {
        response = request.GetResponse();
    }
    catch (Exception::CLRError)
    {
    postdata = "";
    }

    dataStream = response.GetResponseStream();
    streamReader = new System.IO.StreamReader(dataStream);
    returnValue = streamReader.ReadToEnd();

    info(returnvalue);

    streamReader.Close();
    dataStream.Close();
    response.Close();


}

Thursday, February 12, 2015

Easiest say to obtain SID - AX 2012 installation

We often need to obtain SID while installing or moving Dynamics AX across different environments. There are several ways to obtain SID which we need to set in the database table. However, the easiest way to obtain SID is to:

Open command prompt and type the following:

whoami /user

That's it.

Wednesday, December 31, 2014

Applying Current User Id range in an AOT query

If you want to apply a range to an AX 2012 AOT query, you can simply add a new range to the field and specify the integer or string value against them. However, if you want to apply a range on a User Id field and want to provide the value of Currently logged in user, you need to get the value dynamically and pass that value to the query. Below snap shot shows a very simple way to achieve this.


Tips on Extensible Data Security in AX 2012

Recently, I had chance to work on Extensible Data Security and noticed few things which can be very helpful, they are posted below.

  1. XDS can hurt performance sometimes if query is not designed well. In order to design security without hurting the performance, always try to reduce number of joins in your Security Policy Query.
  2. If your requirement is complex and needs to add some dynamic filters to the query. In that case you can create a temporary table with type TEMPDB and override its xds() method to fill the table dynamically. This method can be considered for performance improvements as it would reduce query joins. For this, please see xds method on the table MyLegalEntitiesForXDS
  3. If you have to disable XDS, consider following 2 methods
    1. Create a view and fetch data from that view. View is a different object for XDS framework, thus the security applied on the table will not be considered for view and you will see the data.
    2. Second method to disable the security is mentioned here in my other post.

AX 2012 Disable/ByPass extensible data security (XDS) through code

Extensible Data Security or XDS is a framework introduced in AX 2012 to apply security on data. We had RLS or Record Level Security in AX 2009. However, XDS is completely a new framework with more capabilities in order to apply data security. This post is about disabling or bypassing the XDS using code. For more details about XDS, download a whitepaper provided by Microsoft using following link.
http://www.microsoft.com/en-us/download/details.aspx?id=3110

Disabling/Bypassing XDS or Extensible Data Security:
Recently, I had a requirement to restrict users from viewing all the Warehouses available and they must be able to see only the Warehouses they belong to. I designed a new security policy and it started working very easily without much problem. However, the problem was on Inventory Transfer From where we have two fields for Warehouses:
  1. From warehouse and
  2. To warehouse
Our requirement was to restrict only From warehouse and To warehouse MUST show all the warehouses available so they can issue inventory to any warehouse but should not be allowed to issue inventory from the warehouse they don't belong to. In order to achieve this, I had to disable the XDS on To Warehouse lookup method. I did override the lookup() method on To Warehouse field on the datasource and below is the code which I wrote to disable the XDS.

public void lookup(FormControl _formControl, str _filterStr)
{
    XDSServices                      xXDS = new XDSServices();

    xXDS.setXDSState(0); // Disable XDS
    super(_formControl, _filterStr);
    xXDS.setXDSState(1); // Enable XDS
}

Wednesday, December 17, 2014

AX 2012 showing lookup from different (cross) company

I had a requirement in AX 2012 in which I had to show Customer Lookup from a different company. Our requirement was to provide user with two lookups on the Vendor Form (VendTable).

  1. One lookup - To select the company from which they want to see Customers
  2. Second lookup - Show Customers from the company selected on above lookup
To achieve this I added 2 fields in the table VendTable
  1. TargetCompanyId (EDT: SelectableDataAreaId)
  2. TargetCustAccount (EDT: CustVendAC) - Don't use CustAccount EDT, I tried this in AX2009 and it appeared to be using EDT relation and could not work.
After adding these fields, create a new relationship and add both of the above added fields in this relationship.

Drop the fields on the form and you will see Customer will appear from the company you have selected in the first lookup. Change company from the first lookup and see how data in the customer lookup changes.


Sunday, December 14, 2014

Calling Events of AX Form's Datasource

While working on AX 2012 Forms, we need to call form's datasource events every now and then from other events. Below is the example that shows how you can call any event like modified, validate etc. of a form's datasource from any other method.

Below example shows how you can call modified method of ItemId field under InventJournalTrans datasource.

FormDataObject          itemIdField;
itemIdField = inventjournalTrans_ds.object(fieldnum(InventJournalTrans, ItemId));
itemIdField.modified();
           

Monday, November 24, 2014

Installing Sharepoint 2010 foundation on Windows 7

While trying to Install Sharepoint 2010 on Windows 7 to setup Enterprise Portal, I was getting an error that Windows Server 2008 R2 is needed. I was able to install after adding following setting to the file in the setup directory.

File:
.../SharepointSetup/Files/Setup/Config.xml

Open the above mentioned file and add the following line to it.

<Setting Id="AllowWindowsClientInstall" Value="True"/>

After adding this line, the file would like something like that.

<Configuration>
<Package Id="sts">
<Setting Id="SETUPTYPE" Value="CLEAN_INSTALL"/>
</Package>

        <DATADIR Value="%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\Data"/>

<Logging Type="verbose" Path="%temp%" Template="Microsoft SharePoint Foundation 2010 Setup *.log"/>
<Setting Id="UsingUIInstallMode" Value="1"/>
<Setting Id="SETUP_REBOOT" Value="Never" />
<Setting Id="AllowWindowsClientInstall" Value="True"/>
</Configuration>

Once you add this line, run the setup again and you should be good to go.