23 August 2010

"Exported mappings must come from the same importer" exception


Issue,


Look on the code below,


 ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
                descriptionImporter.ProtocolName = "Soap";
                descriptionImporter.AddServiceDescription(serviceDescription, null, null);
                descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
                descriptionImporter.CodeGenerationOptions = 
                    System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;


                foreach(XmlSchema sc in serviceDescription.Types.Schemas.ToList() )
                {
                    foreach (XmlSchemaObject service in sc.Includes)
                    {
                        if( service is XmlSchemaImport)
                        {
                            XmlSchemaImport schemaImport = service as XmlSchemaImport;


                                                   
                            XmlReader reader = new XmlTextReader(schemaImport.SchemaLocation);


                            descriptionImporter.Schemas.Add( XmlSchema.Read(reader, null));


                        }
                    }
                }

and



 private Assembly CompileAssembly(ServiceDescriptionImporter descriptionImporter)
            {
                // a namespace and compile unit are needed by importer
                CodeNamespace codeNamespace = new CodeNamespace();
                CodeCompileUnit codeUnit = new CodeCompileUnit();


                codeUnit.Namespaces.Add(codeNamespace);


                ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);

as you can in  the  first code fragment, i explicitly extracted the imported schema from the service description (wsdl wrapper), once the code did : ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit); it throw an error, means 2 imported mapping exist, which one to use ? and it this case it throw an exception, what you should do, is , ignoring this code fragment :




 foreach(XmlSchema sc in serviceDescription.Types.Schemas.ToList() )
                {
                    foreach (XmlSchemaObject service in sc.Includes)
                    {
                        if( service is XmlSchemaImport)
                        {
                            XmlSchemaImport schemaImport = service as XmlSchemaImport;

                                                   
                            XmlReader reader = new XmlTextReader(schemaImport.SchemaLocation);

                            descriptionImporter.Schemas.Add( XmlSchema.Read(reader, null));

                        }
                    }
                }


So, damm, its still not working, once you did nothing and the schema (wsdl) has import to ref schema, its still failed to load ref schema element, why ? the servicedescription importer does not import the schema, you should do it manually, so how to do it, the first example present the way, but its still not working, so here the changes you need to do





            WebClient http = new WebClient();
              
            if (webServiceHelperData != null && 
                webServiceHelperData.NetworkCredential != null && 
                !string.IsNullOrEmpty(webServiceHelperData.NetworkCredential.UserName))
            {
                http.Credentials = new NetworkCredential(webServiceHelperData.NetworkCredential.UserName, 
                                                         webServiceHelperData.NetworkCredential.Password);
            }

            // parse wsdl
            serviceDescription = ServiceDescription.Read(http.OpenRead(url), false);
              
            // build an importer, that assumes the SOAP protocol, client binding, and generates properties
            ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
            descriptionImporter.ProtocolName = "Soap";
            descriptionImporter.AddServiceDescription(serviceDescription, null, null);
            descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
            descriptionImporter.CodeGenerationOptions =
                System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
              
            // Download and inject any imported schemas (ie. WCF generated WSDL)          
            foreach (XmlSchema wsdlSchema in serviceDescription.Types.Schemas)
            {
                // Loop through all detected imports in the main schema
                foreach (XmlSchemaObject externalSchema in wsdlSchema.Includes)
                {
                    // Read each external schema into a schema object and add to importer
                    if (externalSchema is XmlSchemaImport)
                    {
                        Uri baseUri = new Uri(url);
                        Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);

                        Stream schemaStream = http.OpenRead(schemaUri);
                        System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);

                        descriptionImporter.Schemas.Add(schema);
                    }
                }
            }

all we do, is adding the 
WebClient.




Enjoy