Tuesday, April 19, 2011

Consume an Currency Exchange Rates Web Service from AX 2009 - WFC

Consuming web services from Ax 2009 is a sort of tricky task when the web service is not DAX 2009 "friendly".


Microsoft published a white paper on how to consume a web service to load currency exchange rates into the ExchRates Tables. The problem is that the web service provider's information is outdated. In addition, this white paper does not really explain the problem the developer will faced when the URL does not have the WSDL definition into it.


For example, in the white paper the web service URL is the following:



http://www.currencyserver.de/webservice

This will return an error saying that there are not discovery services in the URL. Interestly enough, this error will also raise a CLR exception as the CLR object will not be created.


Anyway, I found a free web services with updated currency exchange values that work well with .NET (http://currencyconverter.kowabunga.net/converter.asmx)


So we would do the following:


Go to the AOT > References > Right-Click Add New Service Reference. Add the following information in the pop up window that will come up.

WSDLURL : http://currencyconverter.kowabunga.net/converter.asmx
.NET Code NameSpace : NetExchRateWebReference
Reference Name : NetExchRateWebReference
Service Description : Exchange Rates


When this is done, go to AOT > Classes and create a new class

Class Declaration - Name this any name. My name is AgoExchRatesService

class AgoExchRatesService
{
}


Now create a new method called GetRate and paste the following code:

public static server Exchrate getRate(str _fromCurrency, str _toCurrency,
                                        EUROTriangulation _EUROTriangulation = NoYes::No)
{

    NetExchRateWebReference.ConverterSoapClient soapClient;
    ExchRate    conversionrate;
    ;

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


        //Create the search request
        soapClient = new NetExchRateWebReference.ConverterSoapClient("ConverterSoap");


        //If the currency is triangulated, the from and to currencies must be switched
        if(_EUROTriangulation)
            conversionrate = soapClient.GetConversionRate(_toCurrency, _fromCurrency, systemdateget());
        else
            conversionrate = soapClient.GetConversionRate(_fromCurrency, _toCurrency, systemdateget());


        CodeAccessPermission::revertAssert();
        return conversionrate;
    }
    catch
    {
        throw error(AifUtil::getClrErrorMessage());
    }


}

NOTE: The date parameter is set to DateTime, but just make it date otherwise the function will return 0.

When this is done, go to AOT> Jobs and create a new job and place the following code (Just change the name of the class created in the previous step)

static void EAS_ExchRateJob(Args _args)
{
    ExchRate            exchRate;
    Currency            currency;
    ExchRates           localExchRates;
    EUROTriangulation   euroTriangulation;
    ;

    while select currency
    {
        if(currency.CurrencyCode != CompanyInfo::find().CurrencyCode)
        {
            select forupdate localExchRates where localExchRates.CurrencyCode ==
                             currency.CurrencyCode && localExchRates.FromDate == systemdateget();

            euroTriangulation = (CompanyInfo::find().EuroCurrencyCode != "" ? NoYes::Yes : NoYes::No);
            if(localExchRates.RecId)
            {
                ttsbegin;
                    exchRate = AgoExchRatesService::getRate(currency.CurrencyCode,
                                      CompanyInfo::find().CurrencyCode, euroTriangulation);

                    localExchRates.ExchRate = exchRate * LedgerParameters::find().ExpressExchRate;
                    localExchRates.Triangulation = euroTriangulation;
                    localExchRates.update();
                ttscommit;
            }
            else
            {
                    //Get the current Exchange Rate via web service
                    exchRate = AgoExchRatesService::getRate(currency.CurrencyCode,
                                              CompanyInfo::find().CurrencyCode, euroTriangulation);

                    localExchRates.initValue();
                    localExchRates.CurrencyCode = currency.CurrencyCode;
                    localExchRates.FromDate = systemdateget();
                    localExchRates.ExchRate = exchrate * LedgerParameters::find().ExpressExchRate;
                    localExchRates.Triangulation = euroTriangulation;
                    localExchRates.insert();
             }
          }
    }

}

Now, when you create a new Service Reference in AX 2009, a WCF project is created and stored in E:\Program Files\Microsoft Dynamics AX_UPGRADED\50\Application\Appl\
AX2009UPGRADED\ServiceReferences

NOTE: In my server I placed all the app files on the E drive

Open the APP file (You can open this with Visual Studio) and scroll down to the following code:


<client>
 <endpoint address="http://currencyconverter.kowabunga.net/converter.asmx"
                binding="basicHttpBinding" bindingConfiguration="ConverterSoap"
                contract="NetExchRateWebReference.WcfClient.ConverterSoap" name="ConverterSoap" />
 <endpoint address="http://currencyconverter.kowabunga.net/converter.asmx"
                binding="customBinding" bindingConfiguration="ConverterSoap12"
                contract="NetExchRateWebReference.WcfClient.ConverterSoap" name="ConverterSoap12" />
</client>
Just make sure that your contract in both EndPoints has your service reference name like the one above.

This is, YourServiceReferenceName.WcfClient.ConverterSoap 

Also, when calling the web service in the GetRate method you created earlier, make sure you specify the name for the endpoint, in this case ConverterSoap like the following:

//Create the search request
soapClient = new NetExchRateWebReference.ConverterSoapClient("ConverterSoap");


Run the job and then go to General Ledger > Setup > Exchange Rates and you should see all the values updated.

6 comments:

  1. Awesome..
    Great post.. really looking for this currency conversion service..

    ReplyDelete
  2. good work!
    thanks..

    do you know if there exists official descriptions about the different webservices in ax 2009? For what i'm using wich services, how work it?

    ReplyDelete
  3. Hi Fabian!

    Thanks for following my blog. Regarding your question, if you go to the services node in the AOT, you'll see the services that expose logic from AX. There are not many and they are usually used to create sales orders, purchase orders, etc. Now, you can either extend and/or create new services that can expose a custom logic for example.

    You can also reference external web services as per the post example.

    Take a look at the following:

    http://channel9.msdn.com/Blogs/SanjayJain/Microsoft-Dynamics-AX-2009-AIF-Web-Services-Screencast

    http://technet.microsoft.com/en-us/library/aa496452(v=ax.50).aspx

    http://msdn.microsoft.com/en-us/library/aa609947(v=ax.50).aspx

    https://community.dynamics.com/product/ax/f/33/p/22491/35931.aspx?wa=wsignin1.0

    I hope this helps!

    ReplyDelete
  4. Very good !
    Thank you !
    I am indebted to you.

    ReplyDelete
    Replies
    1. No problem! I'm glad the post helped you out.

      Delete
  5. On consuming the web service, AX compiler passed the first method without errors while the second method was caught as not exist at the class soap client while it is already exist, please advise.

    ReplyDelete

Thank you for your thoughts. Your comment will appear in my blog shortly after review.

Have a great day!