Friday, October 5, 2012

Microsoft Dynamics AX 2012 WS Integration – Hoovers (Company Detail)

Microsoft Dynamics AX 2012
WS Integration – Hoovers (Company Detail)
Purpose: The purpose of this document is to illustrate how to integrate Microsoft Dynamics AX 2012 with Hoovers API.
 
Walkthrough:
 
What if you could offer D&B business information on your own website? What if you wanted something simple and easy to implement? What if it was already done?
 
First off you have to register on D&B website to get access to Hoovers Web Tools: http://dnbdirect.dnb.com/member/register
 
Registration Successful
Your API keys are:

Sales and Marketing API - Sandbox

Key: ABC

Application:
Demo
Key:
ABC
Status:
active
Key Rate Limits
2
Calls per second
5,000
Calls per day
You will receive this information via email, and you will also be able to access your keys through your "my account" area.
Once registered you will receive email with your Username and Password
Thank you for confirming your account.

Welcome to the D&B Direct Developer Community.

The development environment provides you with access to a sample data set to give you an idea of the data elements and the associated data types as well as providing an avenue to see the API in action. D&B Direct WSDL:
http://dnbdirect-sandbox.dnb.com/DnBAPI-10/dnbAPI/dnbAPI.wsdl
D&B Direct WADL:
http://dnbdirect-sandbox.dnb.com/DnBAPI-10/rest/application.wadl
Documentation :
http://developer.dnb.com/service-directory/api-overview/16698839-1.html

For REST Calls please use the following Username and Password.

Username : sandboxAPI
Password : XYZ

Hoovers provides a lot of different APIs and for the purpose of this demo we are interested in REST based interface for Company Detail
 
Hoovers also provides .NET Demo project which allows you to call various API and test them
 
 
Please change configuration settings appropriately to reflect your credentials
<configuration>
       <appSettings>
              <add key="API_KEY" value="ABC"/>
              <!-- Pass in username and password keys to invoke authentication-->
              <!--add key="username" value="Your user name"/-->
              <!--add key="password" value="Your password"/-->
              <add key="username" value=""/>
              <add key="password" value=""/>
       </appSettings>
       <connectionStrings/>
       <system.web>
 
You can open, compile and launch this project in Microsoft Visual Studio and get to the Web interface which allows you to interactively test these APIs as shown below.
 
 
Please note that REST interface requires separate Username and Password which is provided in registration confirmation email
The idea is that we sent the info about customer as it is (as we have it) to Hoovers API and receive a response with potentially amended and/or corrected customer information (Name, CompanyID, DUNS, etc)
For example, XML response message may look like the following
{"name":".Pttnich aiucss,I rlconSoiyOo1","parentName":"0iM","companyId":78808313948824608,"duns":null,"industries":{"allUKSIC":{"item":[{"description":"a ivird isteaMetpiceltcicacDBH","uksic":"1.2580Ejz"},{"description":"sai cvtHtistlioipeaxDg","uksic":"81.510Ovu"}]},"allUSSIC":{"item":[{"description":"e cfihe irihfOaoplr otsncafett5ql","ussic":"000804904qq"},{"description":"csii cPsprsohhtaliyatNlD","ussic":"60083000hoZ"},{"description":"c snfOdecslfdsc icno atrieom foiclia d2Fh","ussic":"18000001QMM"}]},"allNAICS":{"item":[{"description":" usolittey iacPuiHcasbrbtAace Ssn hadsnspUvA","naics":"602221nFz"},{"description":"sl taiisenS a tMnP sffctsfyhipalh,HcceOlioieaes YMG","naics":"216121mwy"}]},"allDnBIC":{"item":[{"description":"hrtSrcoa HtCeee alBiU","dnbic":"31744F "}]},"lineOfBusiness":"N29","primaryDnBIC":"1734Frs","primaryNAICS":"021262s30","primaryUSSIC":"080003065yK","primaryUKSIC":".08151u5X"},"bankName":"z42","spaceAtAddress":null,"ethnicity":"nowUknndIR","phones":{"phoneNumber":[{"countryCode":"ww3","areaCode":"516GAu","phoneNumber":"2-301750R0G","doNotCallRegistry":false}],"faxNumber":[{"countryCode":"lc3","areaCode":"165ITY","phoneNumber":"15311-72T T","doNotCallRegistry":true}]},"synopsis":"ve rtnlomt tckiendcinrsdaaeo>hntdfl rhr tcent ui ipt neafna/0eodsevrp Iceac o l aCayeag<iettrrS airtl0omS o.sco.wp toa Uidcdr rsewah it4casiueoIP ab tnna  r iao o sspy deiednacthye sg .-r1 lwhllmhtpus s asetr nrt o  an ttunrw m isihyoaSteic tSc nCoi-ds hlteir Psve0mdiiota ocyiyufo, ewnstoe yvaslttdlee1 p ahS=rweyPbfiblroeadet 2tbis\"mheidd   5swsitnVt.eataeH )mt ineg  nseup aenui brollil npt c ,nllisIst Ute>gp8uehenetiaaRe9ito Sadsbosit- ahinmph/ci1lIsesidcc t<m.rk,a acl\ni nrot2tTu un m tt pl onfdnm vd t3spyftartoiset teslilaHhnn mb vnhrss t  eieidaiho nuery naeew nn0uihtdlsepaisaaa ah pf eoiassa aq adeasanaihosnrsio cd ilt< IduntUD;r >y etirltoiaerii pptstbs0cen hs i n nif\"acrari0iiavsaor   nrcom.0etenr > sofogocnhss<Uehtnale rh h ceiiwtter(ete1pliSerDxb","ultimateParentDuns":null,"locationType":"qgI","parentDuns":null,"companyType":"LUPCBInyy","dbaNames":{"dba":[]},"topExecutives":{"official":[{"coOfficialId":6007972254570664960,"person":{"prefix":".rMhjA","suffix":"hp7","fullName":"oo aJ. yAbesJchId","firstName":"yeJoCX4","lastName":"bcaosJygM","middleName":".AK3H","age":99436},"connectMail":{"connectMailSource":"enNojkP","connectMailNameSource":true,"connectMailEmailSource":true,"connectMailPhoneSource":true},"latestPosition":{"title":"d,nteCaeasmChEr, i P aOdirnnbml","startYear":"0260rEc","jobFunction":{"jobFunctionId":[745582,56339,82605]},"endYear":"rensPteUaz"},"latestSalary":{"year":1657557,"salary":8903835.9654,"bonus":null,"totalSalary":86.676358383}},{"coOfficialId":5426468768837804032,"person":{"prefix":"r.Mb o","suffix":"sIV","fullName":"c ioFRdan ehnlr.MFFD","firstName":"oadlRnETx","lastName":"cFeihnr8VC","middleName":".Mvqb","age":13488},"connectMail":{"connectMailSource":"DB&TKu","connectMailNameSource":true,"connectMailEmailSource":true,"connectMailPhoneSource":true},"latestPosition":{"title":"COO67v","startYear":"0102EQJ","jobFunction":{"jobFunctionId":[55942]},"endYear":"sPnerte0cl"},"latestSalary":{"year":9291488,"salary":1.627236451E+10,"bonus":null,"totalSalary":2082724763.9}},{"coOfficialId":3912834620384673792,"person":{"prefix":".rMNOF","suffix":"gLg","fullName":"BrenrenTtr uPpU","firstName":"tBernrJv","lastName":"eTurnrMJW","middleName":"viT","age":64255},"connectMail":{"connectMailSource":"eNonzG7","connectMailNameSource":false,"connectMailEmailSource":false,"connectMailPhoneSource":false},"latestPosition":{"title":"cnmViinerEAtsd anP nitondFaai 3vj","startYear":"5002AKf","jobFunction":{"jobFunctionId":[696482,73681,9810]},"endYear":"ntePesrTEw"},"latestSalary":{"year":7876290,"salary":5536418.23,"bonus":null,"totalSalary":9265993.9024}}]},"rankings":{"rank":[]},"minorityOwned":false,"womenOwned":true,"franchiseOperationType":"Xne","ukSpecs":{"numberOfSubsidiaries":null,"ukRegistration":null,"ukVAT":null},"primaryURLs":{"primaryUrl":[{"url":"ohp.:ms.wopunsw/oltticwtsy/bgc","sortOrder":5965}]},"otherURLs":{"url":[]},"accountingFirm":"7Xi","spaceAtAddressAccuracy":null,"numberOfPCs":null,"ownedOrLeased":"wqt","manufacturingIndicator":"Att","foreignTrades":null,"keyFinancials":{"marketValueInfo":{"marketValue":2183.5796784,"marketValueDate":"11015012--uA6"},"incomeAssets":{"period":"0Y92F0J8d","assets":22595.5731,"netIncome":8570.22086,"salesGrowthPercent":881469,"netIncomeGrowthPercent":87.76533}},"keyNumbersHistory":{"annualKeyNumbersHistory":{"keyNumbers":[{"advertising":null,"periodEndMonth":"D920ec 0gMo","fiscalPeriod":"2F090YZza","employeesAtThisLocation":null,"sales":45976796.36,"salesAccuracy":"LCAATU2FK","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"208 c0eDn5I","fiscalPeriod":"00Y28FqPN","employeesAtThisLocation":null,"sales":927364.1131,"salesAccuracy":"CTAUALwRW","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"02 7De0cIiT","fiscalPeriod":"072YF0Tuw","employeesAtThisLocation":null,"sales":6387452585,"salesAccuracy":"TLCAAU3My","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":" 20c0De6a2X","fiscalPeriod":"006Y2FLiA","employeesAtThisLocation":null,"sales":9.46089150E+9,"salesAccuracy":"LACTAU2Ld","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"250e0 DctFw","fiscalPeriod":"FY2500ryQ","employeesAtThisLocation":null,"sales":16.4716225,"salesAccuracy":"CTALAUfG3","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"0c 4e20D9Xh","fiscalPeriod":"Y04F02oK8","employeesAtThisLocation":null,"sales":635841.14,"salesAccuracy":"CAUTLAgel","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"23c00eD hHH","fiscalPeriod":"3Y200FqxO","employeesAtThisLocation":null,"sales":5787.87967,"salesAccuracy":"ATAULCn S","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"0e0D 2c24tP","fiscalPeriod":"0202FY6mQ","employeesAtThisLocation":null,"sales":652658874,"salesAccuracy":"LTAAUCTjJ","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"1e c20D0ZF9","fiscalPeriod":"2Y1F00C9k","employeesAtThisLocation":null,"sales":370032.76,"salesAccuracy":"ULTACAtny","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"0D00c2 eT7 ","fiscalPeriod":"2F00Y0kBI","employeesAtThisLocation":null,"sales":3516.6627,"salesAccuracy":"AACULToq6","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null}]},"quarterlyKeyNumbersHistory":{"keyNumbers":[{"advertising":null,"periodEndMonth":"0e Sp210izo","fiscalPeriod":"01032Qm3j","employeesAtThisLocation":null,"sales":262723.657,"salesAccuracy":"CAAULTSZe","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"nu0102 JgM4","fiscalPeriod":"1Q0220MWG","employeesAtThisLocation":null,"sales":54193308.1,"salesAccuracy":"ACLUTAjJN","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"a0r012 MLjv","fiscalPeriod":"00Q121WFg","employeesAtThisLocation":null,"sales":197.228654,"salesAccuracy":"TLACUAMul","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"09D02e c0SX","fiscalPeriod":"90Q240xvH","employeesAtThisLocation":null,"sales":4496.74655,"salesAccuracy":"ATAUCLkGJ","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"S90p e0201y","fiscalPeriod":"32Q090ZcO","employeesAtThisLocation":null,"sales":1243.7844,"salesAccuracy":"TUCAALeOn","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":" J20u0n9sGX","fiscalPeriod":"09202Qlv8","employeesAtThisLocation":null,"sales":1080920.31,"salesAccuracy":"TLAUACtYd","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null},{"advertising":null,"periodEndMonth":"0rM9a0 2ynl","fiscalPeriod":"Q92100fAl","employeesAtThisLocation":null,"sales":77150171,"salesAccuracy":"CAULATPSa","employeesAtThisLocationAccuracy":null,"totalEmployeeGrowthPercent":null,"employeesTotal":null,"employeesTotalAccuracy":null,"researchAndDevelopment":null}]}},"vat":null,"crn":null,"locations":{"location":[{"state":"TNkeS","country":"t nUitsdteaSe0zn","latitude":null,"longitude":null,"countryId":12584,"county":"SUG","city":"FriknnlaJ6J","metroArea":"lareal-oor-lonkTbersNre-fhMDauid--vvsiNnFsin  uX","zip":"730676xI","address1":"sw6t.4r6hor0eyCk  PaHWX","address2":"0et5S. 0OI8","latLongAccuracy":"91s","stateOfIncorporation":null,"zip4":"Wlj","addressType":"SRRP_MDREIADAYSRIW"}]},"stocks":{"tickerUS":null,"exchangePrimary":null,"exchangeInfoList":null},"nonMarketableCompany":{"reason":[" iO beuosutnsfsnqZ"]},"fein":null,"ultimateParentName":" yC","ultimateDomesticParent":null,"ultimateDomesticParentName":"u6V","ownershipYear":"j9k","fullDescription":"oHi. na\ndas dpsent fhlyureHwwiincea t>  heplaAbwcs tabisetl nselp e r02otfrrcdT  bHn 0y.t  rrl ers .2syai -enti ,ieptadhaqo caitsoph 9pr\n  n tleieuauorrt.toaehiiaoo1l ua >t6ti<ieao 0oiieoarh HsiystahaeocdzcsroiclU iso z nanOltno2b0loogdatrdai ehansin egsn9s rr ci aiMne sfatiCroo t Ppser mdh os/tn,s d heysn fdmi7ainHsg>eeceiwh)astnt;<aa n sinPrs<  hfte $nini9ipaaym  de  lCtetgeep oStt u  .h eate  <srsal he<a g fi to0eqt Sn  o iaaS >ubUMlrmpusnc dntweie ,r0trhpamcssataccHeaailoie gfinsepsornr tegrh 9asUrlr  ihs dne ootndc>  0ash ccUea emo sfeoaeheofip>aaruAn  iote 9  Seorc ol weoa>0aetciuxchmilrhm2e  emimoptdacr oetgtotenihsieet0ynot'ethaelcteno dnt2at et iboitpint- dnyoolsespa w leo coanotsha3w0 tnsahesrle\nntf li  de iolcPatlhsoe\nitbcehiapl e2g i snTlernhyd5,a  Sscoon\nafrfaesil)irhH i'd ef uouttnniarhpo<.lTaautmmttuapr o-apdcfalftr/yoneb ihbLsa< imncpi8nte ikSmockt/ ecasmrnmr>resenfrtdwUH m n\nnecos sv i siat o m  nc e  0sMbtnn ana crd  meoo% yhobIf - eyibrih0bTenipif<PvaSnon(eoss1atcn,roclharbucp <ecni9.stc whtt vcmma ehyi1ses.aanooegsefaih rh<   hnu   t etsce$n agv heordmb fagora.rr<hknhnsnc eed rg tn ite i pl.oeDn> yi plic-onpSospbeeietun, oop tedwctp<l es2rdsnihneilv(shesnsiuvwshr trme tat gc ire eitut rps aarhesiufnht yHtsuagf nri/ia naas d rtobmi hdct d0$d  e.ih th.essaitegpphytpo t<ntsrion sTadiu ulma2>otdv ohrclip, faahstilssw h%sdap,atdll.roicdtSn oictegrtr luls it  ,neP hlS t  ie eeitoc n<leso matrarseoeia mt,esndtcitnisuwcclatDPfttp.neaalortnucefet in  0aoi-yspiiBcp>a cnntlIpr Hrsdisvnbnf hsdwcpaPsoi1av uncytRy o tme\"ynfts=nl0l ee 4nsmli >nr2heslples/ehc3c-cC.r7mtr ye d rl  da  e giisoda ona   rhv8 eg ,oiyvagiirIntcptyrn> dpy  lSniPdi fiirlepaUmusemi s<huwt< n siaa nre u ntytla%nlhai ia-bprgUieina sirli ony;iIvascsnoSrrns  eiiSnee  edcptdaairbeuhco.ne lsa taca dditnorond. rauioo1nyo rit1xeim   etli/spaPdcoRgt \ntcnasiP ei> iiearbarh eet dgScpeesh nlhC> rgpmf emev setlRae  o iihyds ctuiidi hnin c oyaliio ah uaitlMvsiniona ostoPioihldoa eaiiyifyihho i  iyoalnelsw0prdnf i('  pligeV  yeocn 0iymhdpeaoy \nbn\"tfnp maeeio thsvldgtef  hriil Hps tn fnrui c lt r rti m>e2ieriesrt en    oe iIo doa gc\" o<ne\n \"eemm lisvneaotblmn,yr eabe h e>n8 v/s,eirya oie3lrhtpuhnin sasabndttfovbpa dex ts  etdfcecSq P  ueusPeuorstetdcS  go 0, th peio s ltcee1%tyias ra  vrdrhlsd7/n-p0'e tredlpaurxel hO ttiyi teecu0luta s  rsesaCepe twucrsrylantluPe oFPtcliieuhia/g bt  niiiH0a.ollmriva ah  )sn\nari do ppao>c\ne0 nieuced  aiaon0cyn Ial.dveaeonab0aotitme tn-obmfete ral\noeero<qa cennwlialt  a1pbeittsttrS aaayonmenm ieneith ns0min nt.ctouontnp/l liaebipcmtio4tcoiaa=snarcfuosldiSrtboplidrranacecwi i   nkd u0uoaonanBsu ci 0e23NF","historicalText":"aUot qi n ch)r beli 0Ussea0rihh iaol1t. aiclsStyPHwyrSHsctS( e ncangv ilrnp svdei ouaiast2uie36r","marketingPreScreenScore":"LY ","spaceAtAddressUnitOfMeasurement":"qf tsbqf","yearFounded":"Ehz","legalStatus":"YTg","historicalIndicator":true,"smallBusinessIndicator":true,"subsidiaryStatus":false}
 
 
Once you know the details of REST endpoint and the format of response of XML message you are ready to implement the integration
 
C#.NET Class Library (DLL)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;
using System.IO;
 
namespace Hoovers
{
    public class Hoovers_CV
    {
        private const String REST_ENDPOINT = "http://dnbdirect-sandbox.dnb.com/DnBAPI-11/rest/";
       
        private string AX_AccountNum;
        private string AX_Name;
        private string AX_DUNS;
 
        private string Hoovers_Name;
        private string Hoovers_CompanyID;
        private string Hoovers_DUNS;
 
        private bool result;
 
        public string AXAccountNum { get { return AX_AccountNum; } set { AX_AccountNum = value; } }
        public string AXName { get { return AX_Name; } set { AX_Name = value; } }
        public string AXDUNS { get { return AX_DUNS; } set { AX_DUNS = value; } }
 
        public string HooversName { get { return Hoovers_Name; } set { Hoovers_Name = value; } }
        public string HooversCompanyID { get { return Hoovers_CompanyID; } set { Hoovers_CompanyID = value; } }
        public string HooversDUNS { get { return Hoovers_DUNS; } set { Hoovers_DUNS = value; } }
 
        public bool Result { get { return result; } set { result = value; } }
 
        private void addAuthenticationHeaders(WebClient request)
        {
            String username_header = "username:" + "sandboxAPI";
            String password_header = "password:" + "XYZ";
            String apikey_header = "API-KEY:" + "ABC";
            request.Headers.Add(username_header);
            request.Headers.Add(password_header);
            request.Headers.Add(apikey_header);
        }
       
        public void validate()
        {
            WebClient serviceRequest = new WebClient();
            String endpoint = REST_ENDPOINT + "company/16210000000000";
            this.addAuthenticationHeaders(serviceRequest);
            string response = serviceRequest.DownloadString(new Uri(endpoint));
 
            int iName = response.IndexOf("\"name\":") + 7;
            int iCompanyID = response.IndexOf("\"companyId\":") + 11;
            int iDUNS = response.IndexOf("\"duns\":") + 6;
 
            int jName = response.IndexOf(",\"parentName\"", iName);
            int jCompanyID = response.IndexOf(",\"duns\"", iCompanyID);
            int jDUNS = response.IndexOf(",\"industries\"", iDUNS);
 
            Hoovers_Name = response.Substring(iName + 1, jName - 1 - (iName + 1));
            Hoovers_CompanyID = response.Substring(iCompanyID + 1, jCompanyID - 1 - (iCompanyID + 1));
            Hoovers_DUNS = response.Substring(iDUNS + 1, jDUNS - 1 - (iDUNS + 1));          
        }
    }
}
 
Please note that I added the following Service Reference to Hoovers Web Service
 
C#.NET Console Application (.NET Client for testing)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hoovers;
 
namespace HooversClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Hoovers_CV client = new Hoovers_CV();
            client.validate();
 
            Console.WriteLine(client.HooversCompanyID);
            Console.WriteLine(client.HooversDUNS);
            Console.WriteLine(client.HooversName);
 
            Console.Write("Done!");
            Console.ReadLine();
        }
    }
}
 
Result in .NET:
 
Once DLL that implements Hoovers integration is compiled you can complete a programming part in Microsoft Dynamics AX 2012
 
Please add a reference to Hoovers.DLL in References in Microsoft Dynamics AX 2012
Please note that you have to either put Hoovers.DLL in Client Bin directory or register DLL in GAC on Client/Server (depending where the code will be executed)
 
For the sake of simplicity I put Hoovers.DLL into Client Bin folder, created a reference to it in References node in AOT and restarted the Client
 
X++ (Calling DLL validate method)
void clicked()
{
    CodeAccessPermission permission;
 
    Hoovers.Hoovers_CV CV;
 
    CustAccount    AX_AccountNum;
    DirPartyName   AX_Name;
    LogisticsDunsNumber AX_DUNS;
 
    System.String Hoovers_CompanyId;
    System.String Hoovers_Name;
    System.String Hoovers_DUNS;
 
    str strHoovers_CompanyId;
    str strHoovers_Name;
    str strHoovers_DUNS;
 
    boolean result = false;
 
    super();
 
    permission = new InteropPermission(InteropKind::CLRInterop);
 
    permission.assert();
 
    CV = new Hoovers.Hoovers_CV();
 
    AX_AccountNum = AXAccountNum.text();
    AX_Name = AXName.text();
    AX_DUNS = AXDUNS.text();
 
    CV.set_AXAccountNum(AX_AccountNum);
    CV.set_AXName(AX_Name);
    CV.set_AXDUNS(AX_DUNS);
 
    CV.validate();
 
    //result = CV.get_Result();
 
    Hoovers_CompanyId = CV.get_HooversCompanyID();
    Hoovers_Name = CV.get_HooversName();
    Hoovers_DUNS = CV.get_HooversDUNS();
 
    if (Hoovers_CompanyId != null)
        strHoovers_CompanyId = Hoovers_CompanyId.ToString();
 
    if (Hoovers_Name != null)
        strHoovers_Name = Hoovers_Name.ToString();
 
    if (Hoovers_DUNS != null)
        strHoovers_DUNS = Hoovers_DUNS.ToString();
 
    HooversCompanyId.text(strHoovers_CompanyId);
    HooversName.text(strHoovers_Name);
    HooversDUNS.text(strHoovers_DUNS);
}
 
Please see full XPO and AX model with the source code of the Hoovers API Integration here:  <Integration Pack v1 link> 
 
Result in Microsoft Dynamics AX 2012:
Microsoft Dynamics AX 2012 – Sales order header
 
Hoovers Customer Verification dialog
 
Please note that this Integration works in Test mode that's why Hoovers Web Service returns random data
Please note that "Transfer customer" function is not currently implemented because in Test mode Hoovers Web Service returns random data
 
Summary: In this walkthrough I demonstrated how to implement Integration of Hoovers API with Microsoft Dynamics AX 2012. Additional UI elements were added to AX 2012 Sales orders form on header to trigger Hoovers Customer Verification dialog. You can use "Validate customer" function to call Hoovers API and have Hoovers API amend and/or correct customer details initially provided. After customer information has been verified you can use "Transfer Customer" function to transfer verified customer information to Customer itself.  
 
More information about Development process using D&B API can be found here: http://developer.dnb.com/
Author: Alex Anikiev, PhD, MCP
 
Tags: Microsoft Dynamics ERP, Microsoft Dynamics AX 2012, Integration, Microsoft .NET, Hoovers API, Customer Verification, Customer Validation, Company Data.
 
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.
 

Microsoft Dynamics AX 2012 WS Integration – USPS (Address Standartization API)

Microsoft Dynamics AX 2012
WS Integration – USPS (Address Standartization API)
Purpose: The purpose of this document is to illustrate how to integrate Microsoft Dynamics AX 2012 with USPS Address Standardization API.
 
Walkthrough:
 
First off you have to register on USPS website to get access to USPS Web Tools: https://secure.shippingapis.com/registration/
 
Thank you for registering to use USPS Web Tools™. You will receive an email within 24 hours containing your unique Web Tools User ID and instructions for next steps. Once you receive your User ID, you can begin your Web Tools API integration. Please note that additional permission is required for our Address Information APIs. If you wish to use these tools, please register your Web Tools User ID at: https://www.usps.com/business/webtools-address-information.htm.
 
Once registered you will receive email with your Username and Password
 
Thank you for registering for the U. S. Postal Service's Web Tools Application Program Interfaces (APIs).  We are providing you with a User ID that serves multiple purposes, as explained below.
 
Your Username is ABC
Your Password is XYZ
 
Your Web Tools User ID, shown above, is required to test and integrate USPS Web Tools APIs.  With this ID, you may begin sending calls to the test server.  Depending on the API, the address to the test server is either http://testing.shippingapis.com/ShippingAPITest.dll or https://secure.shippingapis.com/ShippingAPITest.dll.  Use this information in combination with your User ID and your XML string to send a request to the USPS servers.  For more details, refer to the programming guides (located at http://www.usps.com/webtools) for the specific API you are integrating.
 
 
When you have completed your testing, email the USPS Internet Customer Care Center (ICCC).  They will switch your profile to allow you access to the production server and will provide you with the production URLs.
 
USPS provides a lot of different Address related APIs and for the purpose of this demo we are interested in Address Standardization API
 
Address Standardization
Eliminate addressing errors and help ensure accurate and timely delivery. This tool corrects errors in street addresses, including abbreviations and missing information. It also supplies a ZIP+4 Code.
 
ZIP Code Lookup
Find matching ZIP Codes or ZIP+4 Codes for any given address, city, and state in the U.S.
 
City/State Lookup
Use a ZIP Code to get accurate city and state information.
 
The idea is that we sent the info about address as it is (as we have it) to USPS Address Standardization API and as receive a response with potentially amended and/or corrected address
For example,
Request
Response
6406 Ivy Lane
Greenbelt
MD
6406 IVY LN
GREENBELT
MD
20770
1440
 
Please see examples of request and response XML messages when using USPS Address Standardization API for Success and Failure scenarios 
Success
Request
Response
http://testing.shippingapis.com/ShippingAPITest.dll?API=Verify&XML=<AddressValidateRequest%20USERID="ABC"><Address ID="0"><Address1></Address1><Address2>6406 Ivy Lane</Address2><City>Greenbelt</City><State>MD</State><Zip5></Zip5><Zip4></Zip4></Address></AddressValidateRequest>
<?xml version="1.0"?>
<Address ID="0"><Address2>6406 IVY LN</Address2><City>GREENBELT</City><State>MD</State><Zip5>20770</Zip5><Zip4>1440</Zip4></Address>
</AddressValidateResponse>
 
Failure
Request
Response
http://testing.shippingapis.com/ShippingAPITest.dll?API=Verify&XML=<AddressValidateRequest USERID="ABC"><Address ID="0"><Address1></Address1><Address2>One Microsoft Way</Address2><City>Redmond</City><State>WA</State><Zip5>98052</Zip5><Zip4>7329</Zip4></Address></AddressValidateRequest>
 
<?xml version="1.0"?>
<Address ID="0"><Error><Number>-2147219040</Number><Source>SOLServerTest;SOLServerTest.CallAddressDll</Source><Description>This Information has not been included in this Test Server.</Description><HelpFile/><HelpContext/></Error></Address>
</AddressValidateResponse>
 
Once you know the name of the API and the format of request and response of XML messages you are ready to implement the integration
 
C#.NET Class Library (DLL)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;
using System.IO;
 
namespace USPS
{
    public class USPS_AV
    {
        private string AX_Street;
        private string AX_City;
        private string AX_County;
        private string AX_State;
        private string AX_Country;
        private string AX_Zip;
       
        private string USPS_Address1;
        private string USPS_Address2;
        private string USPS_City;
        private string USPS_State;
        private string USPS_Zip5;
        private string USPS_Zip4;
 
        private bool result;
 
        public string AXStreet { get { return AX_Street; } set { AX_Street = value; }}
        public string AXCity { get { return AX_City; } set { AX_City = value; }}
        public string AXCounty { get { return AX_County; } set { AX_County = value; }}
        public string AXState { get { return AX_State; } set { AX_State = value; }}
        public string AXCountry { get { return AX_Country; } set { AX_Country = value; } }
        public string AXZip { get { return AX_Zip; } set { AX_Zip = value; }}
 
        public string USPSAddress1 { get { return USPS_Address1; } set { USPS_Address1 = value; } }
        public string USPSAddress2 { get { return AX_Street; } set { USPS_Address2 = value; } }
        public string USPSCity { get { return USPS_City; } set { USPS_City = value; } }
        public string USPSState { get { return USPS_State; } set { USPS_State = value; } }
        public string USPSZip5 { get { return USPS_Zip5; } set { USPS_Zip5 = value; } }
        public string USPSZip4 { get { return USPS_Zip4; } set { USPS_Zip4 = value; } }
 
        public bool Result { get { return result; } set { result = value; } }
 
        public void validate()
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
 
            try
            {
                request = WebRequest.Create(String.Format("http://testing.shippingapis.com/ShippingAPITest.dll?API=Verify&XML=<AddressValidateRequest USERID=\"ABC\"><Address ID=\"0\"><Address1>{0}</Address1><Address2>{1}</Address2><City>{2}</City><State>{3}</State><Zip5>{4}</Zip5><Zip4>{5}</Zip4></Address></AddressValidateRequest>",
                    "", AX_Street, AX_City, AX_State, "", "")) as HttpWebRequest;
 
                using (response = request.GetResponse() as HttpWebResponse)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
 
                    XDocument xmlDocument = new XDocument();
 
                    xmlDocument = XDocument.Parse(reader.ReadToEnd());
 
                    XElement address = xmlDocument.Root.Element("Address");
 
                    XElement error = address.Element("Error");
 
                    if (error == null)
                    {
                        XElement address1 = address.Element("Address1");
 
                        if (address1 != null)
                            USPS_Address1 = address1.Value;
 
                        XElement address2 = address.Element("Address2");
 
                        if (address2 != null)
                            USPS_Address2 = address2.Value;
 
                        XElement city = address.Element("City");
 
                        if (city != null)
                            USPS_City = city.Value;
 
                        XElement state = address.Element("State");
 
                        if (state != null)
                            USPS_State = state.Value;
 
                        XElement zip5 = address.Element("Zip5");
 
                        if (zip5 != null)
                            USPS_Zip5 = zip5.Value;
 
                        XElement zip4 = address.Element("Zip4");
 
                        if (zip4 != null)
                            USPS_Zip4 = zip4.Value;
 
                        result = true;
                    }
                    else
                    {
                        result = false;
                    }
                }
            }
            catch
            {
                result = false;
            }
        }
    }
}
 
C#.NET Console Application (.NET Client for testing)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using USPS;
 
namespace USPSClient
{
    class Program
    {
        static void Main(string[] args)
        {
            USPS_AV client = new USPS_AV();
            client.AXStreet = "6406 Ivy Lane";
            client.AXCity = "Greenbelt";
            client.AXCounty = "";
            client.AXState = "MD";
            client.AXCountry = "";
            client.AXZip = "";
 
            client.validate();
 
            Console.WriteLine(client.USPSAddress1);
            Console.WriteLine(client.USPSAddress2);
            Console.WriteLine(client.USPSCity);
            Console.WriteLine(client.USPSState);
            Console.WriteLine(client.USPSZip5);
            Console.WriteLine(client.USPSZip4);
 
            Console.ReadLine();
        }
    }
}
 
Result in .NET:
Please note that ZIP+4 Code was identified based on initial address information provided 
 
Once DLL that implements USPS Address Standardization integration is compiled you can complete a programming part in Microsoft Dynamics AX 2012
 
Please add a reference to USPS.DLL in References in Microsoft Dynamics AX 2012
Please note that you have to either put USPS.DLL in Client Bin directory or register DLL in GAC on Client/Server (depending where the code will be executed)
 
For the sake of simplicity I put USPS.DLL into Client Bin folder, created a reference to it in References node in AOT and restarted the Client
 
X++ (Calling DLL validate method)
void clicked()
{
    CodeAccessPermission permission;
 
    USPS.USPS_AV AV;
 
    LogisticsAddressStreet    AX_Street;// = "6406 Ivy Lane";
    LogisticsAddressCity      AX_City;// = "Greenbelt";
    LogisticsAddressCountyId  AX_County;
    LogisticsAddressStateId   AX_State;// = "MD";
    LogisticsAddressCountryRegionId AX_Country;
    LogisticsAddressZipCodeId AX_Zip;
 
    System.String USPS_Address1;
    System.String USPS_Address2;
    System.String USPS_City;
    System.String USPS_State;
    System.String USPS_Zip5;
    System.String USPS_Zip4;
 
    str strUSPS_Address1;
    str strUSPS_Address2;
    str strUSPS_City;
    str strUSPS_State;
   str strUSPS_Zip5;
    str strUSPS_Zip4;
 
    boolean result = false;
 
    super();
 
    permission = new InteropPermission(InteropKind::CLRInterop);
 
    permission.assert();
 
    AV = new USPS.USPS_AV();
 
    AX_Street = AXStreet.text();
    AX_City = AXCity.text();
    AX_County = AXCounty.text();
    AX_State = AXState.text();
    AX_Country = AXCountry.text();
    AX_Zip = AXZip.text();
 
    AV.set_AXStreet(AX_Street);
    AV.set_AXCity(AX_City);
    AV.set_AXCounty(AX_County);
    AV.set_AXState(AX_State);
    AV.set_AXCountry(AX_Country);
    AV.set_AXZip(AX_Zip);
 
    AV.validate();
 
    //result = AV.get_Result();
 
    USPS_Address1 = AV.get_USPSAddress1();
    USPS_Address2 = AV.get_USPSAddress2();
    USPS_City = AV.get_USPSCity();
    USPS_State = AV.get_USPSState();
    USPS_Zip5 = AV.get_USPSZip5();
    USPS_Zip4 = AV.get_USPSZip4();
 
    if (USPS_Address1 != null)
        strUSPS_Address1 = USPS_Address1.ToString();
 
    if (USPS_Address2 != null)
        strUSPS_Address2 = USPS_Address2.ToString();
 
    if (USPS_City != null)
        strUSPS_City = USPS_City.ToString();
 
    if (USPS_State != null)
        strUSPS_State = USPS_State.ToString();
 
    if (USPS_Zip5 != null)
        strUSPS_Zip5 = USPS_Zip5.ToString();
 
    if (USPS_Zip4 != null)
        strUSPS_Zip4 = USPS_Zip4.ToString();
 
    USPSAddress1.text(strUSPS_Address1);
    USPSAddress2.text(strUSPS_Address2);
    USPSCity.text(strUSPS_City);
    USPSState.text(strUSPS_State);
    USPSZip5.text(strUSPS_Zip5);
    USPSZip4.text(strUSPS_Zip4);
}
 
Please see full XPO and AX model with the source code of the USPS Address Standardization API Integration here:  <Integration Pack v1 link> 
 
Result in Microsoft Dynamics AX 2012:
Microsoft Dynamics AX 2012 – Sales order header
 
Microsoft Dynamics AX 2012 – Sales order line
 
USPS Address Verification dialog
 
 
Summary: In this walkthrough I demonstrated how to implement Integration of USPS Address Standardizing API with Microsoft Dynamics AX 2012. Additional UI elements were added to AX 2012 Sales orders form on header and line level to trigger USPS Address Verification dialog. You can use "Validate address" function to call USPS Address Standardizing API and have USPS API amend and/or correct address initially provided. After address has been verified you can use "Transfer Address" function to transfer verified address to Sales order header or line.  
 
More information about USPS Web Tools can be found here: https://www.usps.com/business/webtools.htm
 
Author: Alex Anikiev, PhD, MCP
 
Tags: Microsoft Dynamics ERP, Microsoft Dynamics AX 2012, Integration, Microsoft .NET, USPS Address Standardization API, Address Verification, Address Validation.
 
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.