The following sections provide suggestions and describe issues to be aware of as you develop Web service clients for Microsoft Dynamics NAV 2009.

Returning Data from Codeunit Web Services Using XMLports

Returning an XMLport from a Web service allows you to design schemas and to support multiple complex types on a single method call. For example, you can use an XMLport if you need to get a bookmark back as you work with a Page Web service.

See this blog post for a demonstration of this technique.

Using Specified Properties with Visual Studio to Indicate the Presence of a Value in a Field

When you set a field to a value in the code for a Web service client and then send the value back to the Web service, such as when using the Create or Update operation, the field value is not actually updated to anything but its default value. This issue can occur if you are using proxies that are generated by Visual Studio or the tools in the .NET Framework SDK.

This happens because of how autogenerated proxies and the .NET Framework handle values in XML documents that are exchanged between the Web service and the client. The issue is not specific to Microsoft Dynamics NAV.

Consider the schema for the following two fields on this Customer Card Web service:

  CopyCode imageCopy Code
<xsd:element minOccurs="0" maxOccurs="1" name="Credit_Limit_LCY" type="xsd:decimal" /> 
<xsd:element minOccurs="0" maxOccurs="1" name="Salesperson_Code" type="xsd:string" /> 

Both fields are optional, which means that they may or may not be present in the XML document. One field is a decimal type, and the other field is a string because it is declared as a Text data type in Microsoft Dynamics NAV.

If both values are present, then the XML document should contain the following lines:

  CopyCode imageCopy Code
<Credit_Limit_LCY>1000</Credit_Limit_LCY> 
<Salesperson_Code>JR</Salesperson_Code> 

But if there is no information about the credit limit, then the document should contain the following line:

  CopyCode imageCopy Code
<Salesperson_Code>JR</Salesperson_Code> 

If the credit limit is zero, then the document should contain the following line:

  CopyCode imageCopy Code
<Credit_Limit_LCY>0</Credit_Limit_LCY> 

For the decimal type and all .NET value types, this "present-or-not" state can be controlled in the proxy objects with a Boolean *Specified property:

  CopyCode imageCopy Code
if (salesOrder.Credit_Limit_LCYSpecified)
	there is a value present in salesOrder.Credit_Limit_LCY
else 
	there is no useful value in salesOrder.Credit_Limit_LCY

Consequently, if you assign a value in the value type, then you should also define it as present by setting the accompanying Boolean *Specified property to true:

  CopyCode imageCopy Code
salesOrder.Credit_Limit_LCY = 1000;
salesOrder.Credit_Limit_LCYSpecified = true;

To specify that there is no useful value in the value type salesOrder.Credit_Limit_LCY, set the accompanying Boolean *Specified property to false:

  CopyCode imageCopy Code
salesOrder.Credit_Limit_LCYSpecified = false;

The accompanying value in salesOrder.Credit_Limit_LCY will now be disregarded.

.NET reference types, such as the String class, are handled differently because .NET declarations that are based on those types can be null, which means that they can have an explicit expression of no value present:

  CopyCode imageCopy Code
if (salesOrder.Salesperson_Code != null)
	there is a value present in salesOrder.Salesperson_Code
else 
	there is no value in salesOrder.Salesperson_Code

If you assign a value, then you implicitly also define it as present:

  CopyCode imageCopy Code
salesOrder.Salesperson_Code = "JR";

To specify that there is no useful value in salesOrder.Salesperson_Code, set it to null:

  CopyCode imageCopy Code
salesOrder.Salesperson_Code = null;

Example

  CopyCode imageCopy Code
SalesOrder salesOrder = new SalesOrder();
salesOrder.Order_Date = DateTime.Today;
salesOrder.Order_DateSpecified = true;
salesOrder.Currency_Code = "SEK";

salesOrderService.Create(ref salesOrder);

Preserving Data When Working With a Statically Generated Proxy

You can lose data if you develop a Web service client that interacts with a statically generated proxy. We recommend that you implement a process to prevent this from happening. For example, you can generate your proxy as a part of your automated build of the client.

You can run form 810, Web Services, from the Classic client and publish page 21, Customer Card, as a Web service with Customer as the Service Name value. You can then add a Web reference to this service from a C# console application and insert the following code in the Main method:

C#  CopyCode imageCopy Code
static void Main(string[] args)
{
  CustomerService.Customer_Service svc 
	= new CustomerService.Customer_Service();
  svc.UseDefaultCredentials = true;
  Customer c = svc.Read("01121212");
  Console.WriteLine(c.Name);
  Console.ReadKey();
}

When you run the application, you will see the following output:

  CopyCode imageCopy Code
Spotsmeyer's Furnishings

You can then go back to page 21 and set the Name property for the control that is bound to the Name field to CustomerName, and save the page.

Finally, you switch back to the console application without updating the Web reference and run the code. Instead of getting an error message that indicates that the Web request does not match the Web service description, you do not get an error message, and Console.WriteLine shows an empty line.

Similarly, a client Web service cannot detect if a field has been removed from a page since a proxy was last generated.

See Also