Category Archives: Web Services

Building and using MS Project 2010 proxy assembly for WCF PSI Service

To do the task of integrating Microsoft Dynamics NAV 2009 R2 and MS Project Server 2010 I have decided to use WCF interface. WCF interface is provided by PSI (Project Server Interface) which has both ASMX object model and WCF object model implemented.

There are three options for communicating with WCF interface of MS Project Server:

  1. Compiling ProjectServerServices.dll PSI proxy assembly.
  2. Add a PSI proxy source code to the Visual Studio solution.
  3. Add a service reference by using Visual Studio.

I have decided to use the first option and compile ProjectServerServices.dll proxy assembly.

Project 2010 SDK

First you need to download and install Project 2010 SDK from Microsoft Download site (Project 2010 Reference: Software Development Kit).

After you have installed Project 2010 SDK you need to go to the installation folder. In my case that was folder: C:\Program Files (x86)\Microsoft SDKs\Project 2010\Documentation\Intellisense\WCF. Unpack the Source.zip file, found in that folder, so you get the Source subfolder containing C# source files.

Next, you need to start CompileWCFProxyAssembly.cmd to create ProjectServerServices.dll file. The best way to do it is to open Command prompt with administrative privileges (Start->All Programs->Accessories->Command prompt then right click and select Run as administrator), then cd to the C:\Program Files (x86)\Microsoft SDKs\Project 2010\Documentation\Intellisense\WCF and then run CompileWCFProxyAssembly.cmd.

Note: You need to change the path of sn (sn.exe) to the location of Windows SDK in CompileWCFProxyAssembly.cmd. In my case that was C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64\sn.exe.

After the script has run you should have ProjectServerServices.dll in this folder.

Visual Studio

In Visual Studio you shoud add reference by clicking right mouse button on Reference folder in your C# project then select Add reference… option, then select Browse on the left hand side of the Reference Manager window and click Browse… button on the lower side of the window. Navigate to C:\Program Files (x86)\Microsoft SDKs\Project 2010\Documentation\Intellisense\WCF\ProjectServerServices.dll file and click Add button. Click OK to close the Reference Manager window.

Now have fun with connecting to the MS Project Server PSI using WCF interface.

Explicit error handling when working with XMLPort

During my development of Dynamics NAV Web Services for client’s integration with with their web shop I have had unforseen behaviour of XMLPorts.

When you use SETTABLEVIEW function of XMLPort to narrow data to export you use some kind of input parameter (or parameters) you can do something like this:

GetShipToAddress(CustID : Code[20];VAR XMLShipToAddress : XMLport "Ship To Address")
IF CustID <> '' THEN BEGIN
 ShipToAddressLoc.RESET;
 ShipToAddressLoc.SETRANGE("Customer No.",CustID);
 XMLShipToAddress.SETTABLEVIEW(ShipToAddressLoc);
END;

But with this approach you risk the unintentional exposure of all data. Because of using XMLPort as VAR there is no filter in XMLPort – unless defined otherwise on Node element in XMLPort used.

When XMLPort is used in function exposed as web service of codeunit it is “automagically” populated with data AFTER the function has finished. Therefore, if no filter is set on XMLPort it is populated with ALL data from that/those tables used in it.

The secure way of doing this is with proper error handling. Something like this:

GetShipToAddress(CustID : Code[20];VAR XMLShipToAddress : XMLport "Ship To Address")
IF CustID <> '' THEN BEGIN
 ShipToAddressLoc.RESET;
 ShipToAddressLoc.SETRANGE("Customer No.",CustID);
 XMLShipToAddress.SETTABLEVIEW(ShipToAddressLoc);
END ELSE BEGIN
 ERROR(Text001);
END;

When inserting data though web services using XMLPort you should just use XMLPort.IMPORT function in you exposed web service function. All other required data checking should be done in OnBeforeInsertRecord trigger of Table element in XMLPort.

ShipToAddressTable - Import::OnBeforeInsertRecord()
IF ("Ship-to Address"."Customer No." = '') THEN
 ERROR(Text001);
IF ("Ship-to Address".Code = '') THEN
 ERROR(Text002);

When calling web service functions from client side, you should be writing your calls within try/catch block of code so you get proper exception/error code.

These are some thing you should have in mind when using XMLPorts in exposed web services to get enhanced security of data.

 

 

Metadata for object of type CodeUnit with id ***** is in a failed state.

While developing Windows Embedded 6.5.3 application for WMS (Warehouse Management System) which relies on Dynamics NAV web services I have encountered rather “familiar” error:

Metadata for object of type CodeUnit with id ****** is in a failed state…. error CS1001: Identifier expected.

OK, I said, I will recompile the object and restart Microsoft Dynamics NAV Business Web Services.

Recompile, restart… same error. What now? Hmm… restart Web Services Windows Service again. Nope!

Went into code and view the last function I have edited. Nothing suspicious. Compile – everything OK. Puf?!

Let’s go to error again (reading it whole this time). Whoa… Error details info:

…Error details: c:\ProgramData\Microsoft\Microsoft Dynamics NAV\60\Server\MicrosoftDynamicsNavServer\source\Codeunit\Codeunit50004.cs(498,163) : error CS1001: Identifier expected

Ok. Let’s open the error details file. It opens in Microsoft Visual Studio Tools for Applications. Went to line 498 and position 163 and I can see the following line of my function (with source in C#) which ends like:

CS1001_identifier_expectedThere is Int32 param in my function without identifier (which the error clearly states)!

Went back to my codeunit in NAV and opened C/AL locals of the function I have edited and I have something to see. There is a parameter WITHOUT NAME of Integer Type.

dynamicsNAV_identifierexpectedSomehow, while editing parameter list I have, inadvertently, created new parameter row, never assigning a name to it. NAV thinks this is OK and allows the codeunit to be compiled, but the NAV Business Web Services doesn’t like this.

Resolution

Resolution was simple. Removed the “unintentional” parameter, recompiled codeunit, restarted NAV Web Service and everything was fine, again. 🙂