WCF LOB Adapter, dealing with TypeMetadata and xsd:Include

Published on : Sep 16, 2011

Category : General

Saravana

Author

Say for example if you want to expose an operation called “AddOperation” which takes 2 input parameters of type “double” and returns a “double” value. If you are building a standard WCF services, you would have defined the interface as shown below. [OperationContract] double AddOperation(double a, double b) But in order to do the same thing in WCF LOB adapter, you would have done something like this
//Param 1
OperationParameter n1 = new OperationParameter("a"
                                        , OperationParameterDirection.In
                                        , QualifiedType.DoubleType, false);
n1.IsOptional = false;
opMetadata.Parameters.Add(n1);

//Param 2
OperationParameter n2 = new OperationParameter("b"
                                        , OperationParameterDirection.In
                                        , QualifiedType.DoubleType, false);
n2.IsOptional = false;
opMetadata.Parameters.Add(n2);

//Result
opMetadata.OperationResult = new OperationResult(QualifiedType.DoubleType, false);
break;
The reason for the complexity is mainly due the dynamic nature of the WCF LOB adapters, often times you’ll be constructing the operation request and response types based on your underlying LOB applications requirement. WCF LOB Adapter SDK comes with rich set of Metadata object model to cater for various situations. That includes
  • Operation/Type Metadata Object Model is used for contract generation
  • ParameterizedOperationMetadata class can be used for most common operation representations (as shown above)
  • StructuredTypeMetadata can be used for most common types representations
  • Metadata object model is extensible by allowing the adapter developer to provide own XML Schema representations for its members using ExportXmlSchema methods.
The last option ExportXmlSchema is the one you’ll use when the underlying LOB systems already defined XSD schemas and you just want to reuse it. Example [OperationContract] CustomerResponse GetCustomer(RetailCustomer customer) The EchoAdapter sample and some of the great articles from Sonu Arora’s WCF LOB adapter series all explain about the simple scenario where a types is self contained within a single XSD file. But in reality you’ll be using multiple XSD files together either with xsd:include or xsd:import. I can see an open thread here at msdn forum without a resolution. When you try to deal with schemas that include other schemas, you’ll typically see the following error Error while retrieving or generating the WSDL. Adapter message: The ‘urn:schemas-XXXXX:b2b:WorkItemNo’ element is not declared. The solution to that problem is quite straight forward. In the ExportXmlSchema method, you loop through the included schemas before doing your regular one. In the below example the code in bold is a common schema, and the code below that is what you’ll normally have.
public override void ExportXmlSchema(XmlSchemaExportContext schemaExportContext, MetadataLookup metadataLookup, TimeSpan timeout)
{
    if (schemaExportContext == null)
    {
        throw new AdapterException("Schema export context is null.");
    }

    //Read Common Schemas

    Stream commonXsdFile = Assembly.GetExecutingAssembly().GetManifestResourceStream(COMMOM_METADATA_FILE_NAME);
    using (XmlReader reader = XmlReader.Create(commonXsdFile))
    {
        XmlSchema schema = XmlSchema.Read(reader, null);
        if (!IsComplexTypeAlreadyDefined(schemaExportContext.SchemaSet, schema))
        {
            schemaExportContext.SchemaSet.Add(schema);
            if (!schemaExportContext.NamespacePrefixSet.ContainsKey(this.TypeNamespace))
            {
                schemaExportContext.NamespacePrefixSet.Add(this.TypeNamespace
                    , getUniqueNamespacePrefix(schemaExportContext, 0));
            }
        }
    }


    // Read in XML Schema file or create XmlSchema object yourself
    Stream predefinedXsdFile = Assembly.GetExecutingAssembly().GetManifestResourceStream(CONST_METADATA_FILE_NAME);
    using (XmlReader reader = XmlReader.Create(predefinedXsdFile))
    {
        XmlSchema schema = XmlSchema.Read(reader, null);
        if (!IsComplexTypeAlreadyDefined(schemaExportContext.SchemaSet, schema))
        {
            schemaExportContext.SchemaSet.Add(schema);
            if (!schemaExportContext.NamespacePrefixSet.ContainsKey(this.TypeNamespace))
            {
                schemaExportContext.NamespacePrefixSet.Add(this.TypeNamespace
                    , getUniqueNamespacePrefix(schemaExportContext, 0));
            }
        }
        //reader.Close();
    }
}
Nandri Saravana Kumar