Monday 21 April 2014

How to use XSD2Code for SYSPRO’s Business Objects

When you call one of SYSPRO’s API’s, called a Business Object, via a web service or COM or DCOM or WCF, you need to pass it some XML. That XML is defined in a couple of XSD files. Generating that XML can be done easily in C# or VB .Net using a tool such as XSD2Codewhich is available from http://xsd2code.codeplex.com/. (Note that for Visual Studio 2012, you need XSD2CODE Beta Version 3.5 or later.)
The advantage of using a C# object rather than coding your XML as one big string is you get the advantages including:
  • Intellisense in Visual Studio – it shows you descriptions about each XML element from the XSD file’s annotations
  • Type safety
  • Easier to code: you don’t have to convert your types to strings, nor worry about maximum lengths etc. – it’s all done for you.
( I also tried using Microsoft’s XSD.exe tool, but found XSD2Code to be far superior – it is more configurable and so can be made to fit SYSPRO.)
These instructions are written for XSD2Code version 3.4 with Visual Studio 2010 and SYSPRO 6.1.
  1. Download and install XSD2Code. It integrates naturally with Visual Studio.
  2. From the <SYSPRO installation directory>/BASE/SCHEMAS directory,  add the XSD files for your desired business object into your project. E.g. to call the SORTOI business object, add C:\Syspro61\Base\Schemas\SORTOI.XSD and SORTOIDOC.XSD into your Visual Studio Project. Actually, I prefer to copy the XSD files into the appropriate sub-directory of my Visual Studio project and then add them from there, so that I can put the XSD files under source code control. (I use Mercurial.)
  3. In the Visual Studio Solution Explorer, right-click on the new XSD file and select Run XSD2Code Generation.
  4. Set the following parameters; the rest can stay as their default values. This is the key bit:
    1. PropertyParams/GeneratePropertyNameSpecified must be None, otherwise you won’t get parameters generated unless you set the correspondingfieldSpecified to true.
    2. Set the Code/NameSpace to <your-namespace> + the XSD name, so that there aren’t clashes with other XSD’s that use the same internal variables. E.g. I set mine to Syspro.Base.Schema.SORTOI and Syspro.Base.Schema.SORTOIDOC.
    3. Set the Code/TargetFramework to Silverlight or Net40 as appropriate.
    4. Leave the Serialization/DefaultEncoder as UTF-8.
    5. Set Serialization / Enabled to True. This saves you having to write your own serialization routine.
    6. Set Serialization / GenerateXMLAttributes to True.
  5. Press the Generate button.

Here is a screen shot of settings to use if you are using XSD2Code version 3.5:

Group your files
In the Visual Studio Solution Explorer, to have the newly generated .cs file (e.g. SORTOI.designer.cs) grouped under the XSD file (e.g. SORTOI.XSD), i.e. as a branch UNDER the XSD file instead of as a sibling file, follow these instructions:
  1. Close Visual Studio.
  2. Edit the .csproj file for that project with a text editor (such as vim or Notepad).
  3. Add DependentUpon tags (and open and close the Compile tag).
    E.g. change this line:
    <Compile Include="Schema\SORTOI.designer.cs" />
    to this:
    <Compile Include="Schema\SORTOI.designer.cs">
    <DependentUpon>SORTOI.XSD</DependentUpon>
    </Compile>

Use Namespaces

Note that when you tell XSD2Code what namespace to use, you need to use a different namespace for each XSD file as many of SYSPRO’s XSD files use properties with the same name, and you need to avoid those names clashing.
For example, for SOIRTOI.XSD, you could use a namespace of Syspro.Base.Schema.SORTOI;
for SORTOIDOC.XSD, you could use a different namespace such as Syspro.Base.Schema.SORTOIDOC.In other words, don’t use the same namespace for all your business objects. 
Then, in your C# code, you can add a reference to your Syspro.Base.Schema project, and you might like to write using statements such as these:
using SORTOI = Syspro.Base.Schema.SORTOI;
using SORTOIDOC = Syspro.Base.Schema.SORTOIDOC;
Then you will be able to access the generated objects with minimal namespace paths in your code.

Generate your XML

Now you can create code your XML settings using plain old C# objects as simply as this example:
var SORTOI_Parameters = new SORTOI.PostOrders()
{
 Parameters = new SORTOI.Parameters()
 {
     ValidateOnly = PORTOI.ValidateOnly.Y,
     StatusInProcess = PORTOI.StatusInProcess.N
 }
};

Edit the code to correct List definitions

Some List definitions in SYSPRO’s XSD files don’t seem to be properly declared, so you may have to manually edit the generated code and find all lines that begin with public List and add a line like this above the declaration (change the parameter on the right to match your type):
[System.XML.Serialization.XmlElementAttribute("Item")]
so that the final code looks like this example:
[System.Xml.Serialization.XmlElementAttribute("Item")]
public List<SetupQotNonStockItem> Item
This problem only occurs for certain XSD files (such as WIPTPBDOC.xsd), where-as others such as PORTOIDOC.xsd have perfectly-generated code. My guess is that some of SYSPRO’s XSD files are not well constructed.
(Note that XSD2Code’s GenerateXMLAttributes option creates these XmlElementAttributes automatically… if the XSD code is correct.)

Sometimes the XSD file is incorrect

Sometimes the XSD file is actually incorrect. I am getting such problems reported and corrected if and when I find them. See this forum post for more information.

If you right-click on the XSD file but can’t see “Run XSD2Code generation”

If you right-click on your XSD file but can’t see Run XSD2Code generation enabled, this may be because the highlighted file has just switched to a different file, due to some behaviour in Visual Studio. To work around this, double-click on your XSD file first so that it comes up for editing; then you will be able to right-click on the XSD file and generate code for it.

Serialize your objects

To convert your object to XML, you can use code such as this:
string XmlParameters = SORTOI_Parameters.Serialize();

Syspro’s VBScript Business Objects don’t like namespace declarations

Note that if you may have XML Namespace declarations in your XML from serialization like this:
<Orders xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""">
This shouldn’t be a problem BUT if you are passing this XML to Syspro’s VBScript and then calling a Business Object from VBScript, it will not like the xmlns declaration, so you may want to add this code on the VBSCript side (see related article, How to invoke a Syspro VBScript function from a .Net User Control):
Dim nameSpaceDeclaration
nameSpaceDeclaration = "xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"""
XmlParameters = Replace(XmlParameters, nameSpaceDeclaration,"")
This was the case for Syspro 6.1 Port 69.
However, this doesn’t seem to be an issue if calling the Business Object not from VB Script but from a web service or via DCOM.

Adjust the encoding for Silverlight

If you are using this in Silverlight, you may need to adjust the XML encoding; this is an ugly way of doing it:
XmlParameters = XmlParameters.Replace("encoding=\"utf-8\"", "encoding=\"Windows-1252\"");
A better way of doing this may be to pass the Serialize routine a parameter to select which encoding to use; I have yet to try this.

Finally

Then you can pass those XML strings to the web service for the business object, e.g:
setupProxySORTOI.AddAsync(userId, "SORTOI", XMLParameters, XMLIn);

See Also

No comments:

Post a Comment